EtherealBug
EtherealBug

Reputation: 177

Logical OR in XPath? Why isn't | (pipe symbol) working?

I've got an XSLT template which counts topics at all levels, for use in labeling those topics with numbering in DITA projects I've got.

<xsl:template match="*[contains(@class, ' bookmap/chapter ')] | *[contains(@class, ' map/topicref ')] [not(ancestor-or-self::*[contains(@class,' bookmap/frontmatter ')])]" mode="topicTitleNumber"> 
    <xsl:number format="1 " count="*[contains(@class, ' map/topicref ')] [not(ancestor-or-self::*[contains(@class,' bookmap/frontmatter ')])] | *[contains(@class, ' bookmap/chapter ')]" level="multiple"/> 
</xsl:template> 

I'm trying to add an additional exclusion to what gets counted though, for when a topicref class has a title element with an outputclass of noNum.

<xsl:template match="*[contains(@class, ' bookmap/chapter ')] | *[contains(@class, ' map/topicref ')] [not(ancestor-or-self::*[contains(@class,' bookmap/frontmatter ')])]" mode="topicTitleNumber"> 
    <xsl:number format="1 " count="*[contains(@class, ' map/topicref ')] [not(ancestor-or-self::*[contains(@class,' bookmap/frontmatter ')] | *[contains(title/@outputclass, 'noNum')])] | *[contains(@class, ' bookmap/chapter ')]" level="multiple"/> 
</xsl:template> 

Shown above, I added | *[contains(title/@outputclass, 'noNum')] after the first not statement, thinking that would function as an additional condition in which the count call would skip over when the template was called (i.e. ...not an ancestor-or-self with [criteria] or a topic with title outputclass attribute of 'noNum'...). However it appears that the criteria I added is treated as something the template does match on and count.

Assuming that I am correct on the last point, I believe I need to put that condition inside of its own 'not' statement, but I'm not sure how to do that with the conditions already present in the XPath.

Upvotes: 1

Views: 1033

Answers (1)

kjhughes
kjhughes

Reputation: 111491

In XPath | is a set union operator, not a logical OR.

Union operator, |

XPath 1.0

The | operator computes the union of its operands, which must be node-sets.

XPath 2.0+

The union and | operators are equivalent. They take two node sequences as operands and return a sequence containing all the nodes that occur in either of the operands.


Logical OR, or

Use or instead for logical OR .


Complex XPath still not working?

Break it down to smaller parts:

  1. Does //*[contains(@class, ' bookmap/chapter ')] select what you expect? Repeat for each of the most basic parts of your logical expression individually.

  2. Combine those individually verified terms or predicates, one at a time, and observe that each step along the way, there are not surprises.

  3. Repair any discrepancies between expected and actual results before combining additional terms.

Upvotes: 3

Related Questions