The XPath
transform output is the result of applying the XML canonicalization algorithm
[XML-C14N-a],
parameterized by a given XPath expression, to the XML document received
as the transform input. The XPath expression appears as the character content
of a transform parameter subelement named XPath
.
The primary purpose of this transform is to ensure that only specifically defined changes to the input XML document are permitted after the signature is affixed. The XPath expression can be created such that it includes all elements except those meeting specific criteria. It is the responsibility of the XPath expression author to ensure that all necessary information has been included in the output such that modification of the excluded information does not affect the interpretation of the transform output in the application context.
The XPath transform establishes the following evaluation context for the XML canonicalization algorithm:
XPath
parameter element.The function definition for here()
is consistent with its
definition in XPointer. It is defined as follows:
The here function returns a node-set containing the single node that directly bears the XPath expression. The node could be of any type capable of directly bearing text, especially text and attribute. This expression results in an error if the containing XPath expression does not appear in an XML document.
As an example, consider creating an enveloped signature (a Signature
element that is a descendant of an element being signed). Although the signed
content should not be changed after signing, the elements within the
Signature
element are changing (e.g. the digest value must be put
inside the DigestValue
and the SignatureValue
must be
subsequently calculated). One way to prevent these changes from invalidating the
digest value in DigestValue
is to add an XPath Transform
that omits all Signature
elements and their descendants. For example,
<Document>
...
<Signature xmlns="&dsig;">
<SignedInfo>
...
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
<XPath>(//. | //@* | //namespace::*)[not(ancestor-or-self::Signature)]</XPath>
</Transform>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/02/xmldsig#sha1"/>
<DigestValue></DigestValue>
</Reference>
</SignedInfo>
<SignatureValue></SignatureValue>
</Signature>
...
</Document>
The subexpression (//. | //@* | //namespace::*)
means that all nodes in
the entire parse tree starting at the root node are candidates for the result node-set.
For each node candidate, the node is included in the resultant node-set if and only if
the node test (the boolean expression in the square brackets) evaluates to
"true" for that node. The node test returns true for all nodes except nodes
that either have or have an ancestor with a tag of Signature
.
A more elegant solution uses the here function
to omit only the Signature
containing the XPath Transform, thus allowing
enveloped signatures to sign other signatures. In the example above, use the following
expression as the content of the XPath
element:
(//. | //@* | //namespace::*)
[
count(ancestor-or-self::Signature | here()/ancestor::Signature[1]) > count(ancestor-or-self::Signature)
]
Since the XPath equality operator converts node sets to string values before comparison,
we must instead use the XPath union operator (|). For each node of the document, the
predicate expression is true if and only if the node-set containing the node and its
Signature
element ancestors does not include the enveloped Signature
element containing the XPath expression (the union does not produce a larger set if
the enveloped Signature
element is in the node-set given by
ancestor-or-self::Signature
).
It is RECOMMENDED that the XPath be constructed such that the result of this operation is a well-formed XML document. This should be the case if the root element of the input resource is included by the XPath (even if a number of its descendant nodes are omitted by the XPath expression). It is also RECOMMENDED that nodes should not be omitted from the input if they affect the interpretation of the output nodes in the application context. The XPath expression author is responsible for this since the XPath expression author knows the application context.
An enveloped signature transform T removes the whole Signature
element containing T from the digest calculation of the Reference
element containing T. The entire string of characters used by an XML processor
to match the Signature
with the XML production element
is removed.
The output of the transform is equivalent to the output that would result from
replacing T with an XPath transform containing the following
XPath expression:
(//. | //@* | //namespace::*)
[
count(ancestor-or-self::Signature | here()/ancestor::Signature[1]) > count(ancestor-or-self::Signature)
]
Note that it is not necessary to use an XPath expression evaluator to create this transform. However, this transform MUST produce output in exactly the same manner as the XPath transform parameterized by the XPath expression above.
The Transform element contains a single parameter child element
called XSLT
, whose content MUST conform to the XSL Transforms [XSLT] language syntax.
The processing rules for the XSLT transform are stated in the XSLT specification
[XSLT].