I'm trying to create and xpath expression that returns me the value of a node however I found my self unable to do so as the element is within another element that has a different namespace from the root.
For example I'm trying to retrieve the InternalSystemId from the following xml but traditional XML won't work
XPATH I'm trying to use
/SomeMessage[1]
/MessageDetails[1]
/PAYLOAD[1]
/Call-Name[1]
/Body[1]
/ActionToTake[1]
/Fields[1]
/InternalSystemId[1]
XML I'm have
<?xml version="1.0" encoding="UTF-8"?>
<SomeMessage>
<MessageDetails>
<FROM/>
<TO/&开发者_开发问答gt;
<PAYLOAD>
<Call-Name
xmlns:ns0="http://www.mysite.com/interface/genericnamespace"
xmlns="http://www.mysite.com/interface/genericnamespace">
<Header xmlns="">
<Transaction>
<Mandatory>
<TransactionId>111111</TransactionId>
</Mandatory>
<System-Use-Only>
<Name>Receiver</Name>
<Someone>Customer</Someone>
<Something>OUT</Something>
</System-Use-Only>
</Transaction>
</Header>
<Body xmlns="">
<ActionToTake>
<TransactionName>ActionToTake</TransactionName>
<Fields>
<InterfaceId>w00tie</InterfaceId>
<CustomerSystemId>555555</CustomerSystemId>
<InternalSystemId>4444444</InternalSystemId>
<SubmittedDate
>2011-04-14T12:00:00-00:00</SubmittedDate>
<EventType>A type</EventType>
</Fields>
</ActionToTake>
</Body>
</Call-Name>
</PAYLOAD>
</MessageDetails>
</SomeMessage>
The Call-Name
element is in the namespace whose URI is "http://www.mysite.com/interface/genericnamespace". Therefore you need to either
select it by name using that namespace, or
use a namespace-agnostic method to access it.
The fact that the element is in a different namespace from the "root" (element) is not directly relevant.
To do #1, you have to declare a prefix for the namespace in your XPath execution environment; e.g. in an XSLT stylesheet you could put xmnls:mysite="http://www.mysite.com/interface/genericnamespace"
. Then you would select the element using that prefix and the element name, e.g.
/SomeMessage[1]/MessageDetails[1]/PAYLOAD[1]/mysite:Call-Name[1]/Body[1]/ActionToTake[1]/Fields[1]/InternalSystemId[1]
Of course you could use whatever prefix you like.
To do #2, there are several options. If the Call-Name
element has no siblings, or comes in a stable order among its siblings, you could substitute *
for its name. That way, the XPath will select any element child of PAYLOAD[1]
, regardless of its name or namespace:
/SomeMessage[1]/MessageDetails[1]/PAYLOAD[1]/*[1]/...
Another option, if you're brave and confident about the structure of your input XML, is to use //
to skip over that element:
/SomeMessage[1]/MessageDetails[1]/PAYLOAD[1]//Body[1]/...
If you still need to test by name, but not by namespace, you can use local-name() =
:
/SomeMessage[1]/MessageDetails[1]/PAYLOAD[1]/*[local-name()='Call-Name']/Body[1]/...
精彩评论