问题
I am fairly new to XPATH and need to return a value from multiple XML objects when a certain node is equal to one of two values. The solution also needs to be namespace agnostic using local-name(). Given the following XML, I am looking to return all of the values of "B" where "A" is equal to either "4" or "5".
<?xml version="1.0"?>
<element>
<A>3</A>
<B>Value 1</B>
</element>
<element>
<A>4</A>
<B>Value 2</B>
</element>
<element>
<A>5</A>
<B>Value 3</B>
</element>
I have tried many iterations of the following expression but cannot seem to get the syntax correct when I try to add the second value for "A". I just can't seem to figure out the correct syntax for an "or" expression. I have also considered the use of a union and couldn't get that syntax correct either.
This works for when "A" equals a single value of "4" but how to I add the test for a value of "5" so that the result returns two values for "B" ("Value 2" and "Value 3")?
//*[local-name()='element'][*[local-name()='A']='4']/*[local-name()='B']/text()
Thank you. Any help would be very much appreciated!
回答1:
Try this:
//*[local-name() = 'element']/*[local-name() = 'A' and (. = 4 or . = 5)]
/../*[local-name() = 'B']
This expression selects Value 2
and Value 3
.
回答2:
The proper way of treating namespaces is to register them with your XPath API and to ...use them in the XPath expression:
Use:
//x:element[x:A = 4 or x:A = 5]/x:B
XSLT - based verification:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="some:default NS">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select="//x:element[x:A = 4 or x:A = 5]/x:B"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following XML document (the provided fragment, wrapped by a single top element that has a default namespace definition):
<t xmlns="some:default NS">
<element>
<A>3</A>
<B>Value 1</B>
</element>
<element>
<A>4</A>
<B>Value 2</B>
</element>
<element>
<A>5</A>
<B>Value 3</B>
</element>
</t>
the XPath expression is evaluated and the result (selected nodes) of this evaluation is copied to the output:
<B xmlns="some:default NS">Value 2</B>
<B xmlns="some:default NS">Value 3</B>
回答3:
You can nest predicates.
//*[ local-name() = 'element' and *[local-name() = 'A' and (. = 4 or . = 5)] ]/*[ local-name() = 'B' ]/text()
But in reality you should be using namespace-aware XPath:
//ns1:element[ns2:A[. = 4 or . = 3]]/ns2:B/text()
来源:https://stackoverflow.com/questions/13463871/xpath-selecting-multiple-records-with-wildcard-namespaces