Skip to content

Commit

Permalink
The spec for XML canonicalization REC-xml-c14n-20010315 section 2.4 r…
Browse files Browse the repository at this point in the history
…equires that when canonicalizing a document subset that the namespace attributes from parent elements be included in the subset root element. This change adds support for this requirement.
  • Loading branch information
rowland66 committed Apr 18, 2023
1 parent 1abeb1b commit f3f51b2
Showing 1 changed file with 46 additions and 2 deletions.
48 changes: 46 additions & 2 deletions canonicalize.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,12 @@ func MakeC14N10WithCommentsCanonicalizer() Canonicalizer {
}

// Canonicalize transforms the input Element into a serialized XML document in canonical form.
func (c *c14N10RecCanonicalizer) Canonicalize(el *etree.Element) ([]byte, error) {
func (c *c14N10RecCanonicalizer) Canonicalize(inputXML *etree.Element) ([]byte, error) {
parentNamespaceAttributes, parentXmlAttributes := getParentNamespaceAndXmlAttributes(inputXML)
inputXMLCopy := inputXML.Copy()
enhanceNamespaceAttributes(inputXMLCopy, parentNamespaceAttributes, parentXmlAttributes)
scope := make(map[string]struct{})
return canonicalSerialize(canonicalPrep(el, scope, true, c.comments))
return canonicalSerialize(canonicalPrep(inputXMLCopy, scope, true, c.comments))
}

func (c *c14N10RecCanonicalizer) Algorithm() AlgorithmID {
Expand Down Expand Up @@ -215,3 +218,44 @@ func canonicalSerialize(el *etree.Element) ([]byte, error) {

return doc.WriteToBytes()
}

func getParentNamespaceAndXmlAttributes(el *etree.Element) (map[string]string, map[string]string) {
namespaceMap := make(map[string]string, 23)
xmlMap := make(map[string]string, 5)
parents := make([]*etree.Element, 0, 23)
n1 := el.Parent()
if n1 == nil {
return namespaceMap, xmlMap
}
parent := n1
for parent != nil {
parents = append(parents, parent)
parent = parent.Parent()
}
for i := len(parents) - 1; i > -1; i-- {
elementPos := parents[i]
for _, attr := range elementPos.Attr {
if attr.Space == "xmlns" && (attr.Key != "xml" || attr.Value != "http://www.w3.org/XML/1998/namespace") {
namespaceMap[attr.Key] = attr.Value
} else if attr.Space == "" && attr.Key == "xmlns" {
namespaceMap[attr.Key] = attr.Value
} else if attr.Space == "xml" {
xmlMap[attr.Key] = attr.Value
}
}
}
return namespaceMap, xmlMap
}

func enhanceNamespaceAttributes(el *etree.Element, parentNamespaces map[string]string, parentXmlAttributes map[string]string) {
for prefix, uri := range parentNamespaces {
if prefix == "xmlns" {
el.CreateAttr("xmlns", uri)
} else {
el.CreateAttr("xmlns:"+prefix, uri)
}
}
for attr, value := range parentXmlAttributes {
el.CreateAttr("xml:"+attr, value)
}
}

0 comments on commit f3f51b2

Please sign in to comment.