简体   繁体   中英

XPath 'or' operator using the 'pipe' character?

Within an AutoHotKey routine I'm using MSXML6 to parse an XML document.

doc := ComObjCreate("MSXML2.DOMDocument.6.0")
doc.setProperty("SelectionLanguage", "XPath")
doc.async := false
doc.loadXML(xmldata)
doc.selectNodes("osm/way|rel[tag[@k='railway'][@v='station']]").length

In the SelectNodes line I wish to filter the results to only two nodes: way|rel

It doesn't throw an error but ignores rel returning only way nodes.

This syntax works when using it in Saxon. Is there a solution to this in MSXML, or is there an alternative parser I could implement?

XPath 2.0 is required to use the | within a single XPath like that. MSXML supports only XPath 1.0.

XPath 1.0

@wp78de's answer works (+1), but you can avoid having to duplicate the tag[@k='railway'][@v='station'] condition across | by using the self:: axis within the predicate:

osm/*[(self::way or self::rel) and tag[@k='railway'][@v='station']]

XPath 2.0

For the benefit of later readers who might be using a XPath 2.0 library:

osm/(way|rel)[tag[@k='railway' and @v='station']]

(@wp78de had posted this too prior to realizing that OP was limited to XPath 1.0.)

Since you are using MSXML (v6) you are limited to the features of XML 1.0 ( as defined by the W3C as of v4 ). This means you are not allowed to use alternations on an axis step ( ref ). Therefore, you need to split your path:

doc.selectNodes("osm/way[tag[@k='railway'][@v='station']] | osm/rel[tag[@k='railway'][@v='station']]")

I've tested this end-to-end in PowerShell using MSXML6 via COM and it is working as expected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM