'What exactly does this XPath expression do (count and here)?

This is from the XML Signature specification:

<XPath xmlns:dsig="&dsig;">
count(ancestor-or-self::dsig:Signature |
here()/ancestor::dsig:Signature[1]) >
count(ancestor-or-self::dsig:Signature)</XPath>

The accompanying text says "An enveloped signature transform T removes the whole Signature element containing T from the digest calculation of the Reference element containing T." I don't have a working here() so I can't probe it. I think the text of the specification is a little loose. Consider the following scenario:

<saml2:Assertion ID="2">
 <ds:Signature ID="s1">
  <ds:SignedInfo>
   <ds:Reference URI="#2">
    <ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></ds:Transforms>
   </ds:Reference>
  </ds:SignedInfo>
 </ds:Signature>
 <ds:Signature ID="s2">
  <ds:SignedInfo>
   <ds:Reference URI="#2">
    <ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></ds:Transforms>
   </ds:Reference>
  </ds:SignedInfo>
 </ds:Signature>
 <ds:Signature  ID="s3">
  <ds:SignedInfo>
   <ds:Reference URI="#2">
    <ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></ds:Transforms>
   </ds:Reference>
  </ds:SignedInfo>
 </ds:Signature>
</saml2:Assertion>

With the active node being "s2", which <ds:Signature> nodes are removed?

The system XML library is broken. I can't ask it.



Solution 1:[1]

count(ancestor-or-self::dsig:Signature |
        here()/ancestor::dsig:Signature[1]) >
      count(ancestor-or-self::dsig:Signature)

The expression count(X|Y) > count(X) returns true if Y contains one or more nodes that are not included in X.

I think the [1] is entirely redundant. The expression is true if here() has an ancestor Signature that is not an ancestor-or-self of the context node.

As for what here() does, you'll have to get that from someone who knows the XML Signature spec.

The expression, where it appears in the XML Signature spec, is immediately followed by an explanation: "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". I'm not sure what part of that isn't clear...

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Michael Kay