6.6.3 XPath Filtering

Identifier:
http://www.w3.org/TR/1999/REC-xpath-19991116

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:

The function definition for here() is consistent with its definition in XPointer. It is defined as follows:

Function: node-set here()

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.

6.6.4 Enveloped Signature Transform

Identifier:
http://www.w3.org/2000/02/xmldsig#enveloped-signature

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.

6.6.5 XSLT Transform

Identifier:
http://www.w3.org/TR/1999/REC-xslt-19991116

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].