XPath evaluation failing - xpath

What would be the Xpath code required to get all of the nodes under Price?
So far I have tried AMUpdate/AMMesageType/amprice/Price, which is failing.
<AMUpdate>
<AMMessageType>AMPRICES</AMMessageType>
<amprice:AMPrices xmlns:amprice="http://www/am.com/am/dto/price">
<Price>
<Currency>GBP</Currency>
<Country>LU</Country>
<BusinessLine>AMSL</BusinessLine>
</Price>
</amprice:AMPrices>
</AMUpdate>

Please try below Xpath,
/AMUpdate/amprice:AMPrices/Price/*
You XML have a closing tag missing. Please find the updated XML,
<AMUpdate>
<AMMessageType>AMPRICES</AMMessageType>
<amprice:AMPrices xmlns:amprice="http://www/am.com/am/dto/price">
<Price>
<Currency>GBP</Currency>
<Country>LU</Country>
<BusinessLine>AMSL</BusinessLine>
</Price>
</amprice:AMPrices>
</AMUpdate>
You can try testing XPath here

Related

XMLPath Query for nested XML fragment

I'm trying to write a xpath query to pull data from an xml document. Unfortunately the document has a xml fragment embedded in it that seems to have lost its encoding (< has become &lt > has become &gt etc).
An example of the xml doc is:
<OrderData xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Id>1</Id>
<RawData><?xml version="1.0" encoding="UTF-16"?>
<Data xmlns="nnn-mmm-com">
<Order Action="Remove" >
<Instrument InstID="1"></Order><
/Data>
</RawData>
</OrderData>
I'm trying to extract the following values:
Id
Action
InstID
Getting the Id is no problem, but drilling into the fragment inside RawData is proving beyond me. Any pointers gratefully received
(I'm planning to execute the xpath query in Hive using Hive-XML-SerDe which is xpath 1.0)
Thanks
With XPath 3.1 you can parse the embedded XML document and turn it into a node tree, which you can then process using path expressions. So:
/OrderData/RawData/parse-xml(.)/*:Data/*:Instrument/#InstID
should get what you want.
You didn't say what version of XPath your library supports, which usually means that it only supports 1.0, so you may need to find a different library.

XPath 1.0: Use the attribute value of the current node's parent to find another matching node

I have found many similar posts to this question, but nothing that answers this specific question. I must use XPath 1.0. I do not have XSLT (or XQuery or anything else) available to me, and I cannot use XPath 2.0. I am executing this XPath from inside a piece of software (Arbortext Styler), in which I can use XPath 1.0 to select content from other nodes, but XSLT is not available in this context. Also, I have no control over the structure of the source XML.
When I am in the context of <step>, I need to be able to match a previous procedure/task/step for which that step's parent procedure matches the current procedure's #ref and #seq and has the letter "A" as the value for #conf.
<document>
<topic>
<procedure ref="056" seq="01" conf="A">
<task>
<step>1. Blah Blah (056-01-A)</step>
</task>
</procedure>
<procedure ref="057" seq="02" conf="A">
<task>
<step>2. Blah blah (057-02-A)</step>
</task>
</procedure>
<procedure ref="057" seq="02" conf="B">
<task>
<step>2. Blah blah (057-02-B)</step>
</task>
</procedure>
<procedure ref="057" seq="03" conf="A">
<task>
<step>3. Blah blah (057-02-A)</step>
</task>
</procedure>
</topic>
</document>
What I need is something like this, but without the current() function, which is not supported by the software application:
//procedure[#ref=current()/ancestor::procedure/#ref and #seq=current()/ancestor::procedure/#seq and #conf='A']/task/step
Or something like this, but without the for in return statement:
for $ref in ancestor::procedure/#ref, $seq in ancestor::procedure/#seq return //topic/procedure[#ref=$ref and #seq=$seq and #conf='A']/task/step/text()
Does anyone have any suggestions for how this could be accomplished purely with XPath 1.0? Please note that the position of the procedure cannot be hardcoded. The duplicate refs can occur multiple times and in any position. Also, it is a requirement that this match be done with a starting context of <step>.
I suspect the answer to my question is that it can't be done, but I do know that if it can be done, this is the place to find the answer! Thanks, in advance, to all of you who consider this question.
This post was similar, but the search was looking for children of starting context: Xpath Getting All Nodes that Have an Attribute that Matches Another Node
This was also interesting, but my attribute value is not an ID: Xpath: find an element value from a match of id attribute to id anchor
Any suggestions?
As suggested by both Tomalak and Honza Hejzl, this cannot be done with XPath 1.0. Thanks for the feedback.

Selecting updated timestamp using XPath

XPath noob question:
I have an HTML file that contains
<p class="postinginfo">Updated: <time datetime="2013-11-21T12:39:50-0600">2013-11-21, 12:39PM CST</time></p>
<p class="postinginfo">Posted: <time datetime="2013-11-20T12:39:50-0600">2013-11-20, 12:39PM CST</time></p>
I'm trying to extract the time using C# and HtmlAgilityPack
var htmldocs = doc.DocumentNode.SelectNodes("//*[#class=\"postinginfo\"]Updated:/text()");
This did not work. Reading through the XPath tutorial on w3schools.com it wasn't obvious how the functions should be used. I'd appreciate some guidance from a more experienced XPath user.
I'd suggest you install firefox+firebug+firepath to test xpath expression.
Try this xpath:
//p[#class='postinginfo' and contains(., 'Updated:')]/time/#datetime

Nokogiri xpath query results in String instead of NodeSet

I have a Nokogiri node which I'm doing an xpath query on which should return a NodeSet. Instead it returns a String. I checked the xml source and found that the data only contains one element instead of many.
Shouldn't it return a NodeSet with only one value, instead of a String? How do I deal with this?
Here's the pseudo xml which correctly returns a NodeSet with 2 entries:
<root>
<products>
<product>
<productID>1</productID>
</product>
<product>
<productID>2</productID>
</product>
</product>
</root>
Here's the pseudo xpath query:
//root/products/product
If the xml only contains one product, I get a String instead of a NodeSet with 1 entry
<root>
<products>
<product>
<productID>1</productID>
</product>
</product>
</root>
Update 6/12/2012: I still believe this is a bug in Nokogiri.The above pseudo xml does not reproduce the condition, however I have several xml examples from a client which do reproduce the issue. I could probably post an obfuscated version of the xml. In any case I have changed the code to use XmlSimple instead of Nokogiri.
Works for me:
require 'nokogiri'
xml = "<root><products>
<product><productID>1</productID></products>
</product></root>"
p Nokogiri.XML(xml).xpath('//root/products/product').class,
#=> Nokogiri::XML::NodeSet
Nokogiri::VERSION,
#=> "1.5.2"
RUBY_DESCRIPTION
#=> "ruby 1.9.3p125 (2012-02-16) [x86_64-darwin11.3.0]"
Either your version of Nokogiri is bad (leaning on a bad libxml2 version, likely), or your code is sufficiently different that you need to provide us with a way to reproduce your problem.
I ran into this "issue" as well, but after a bit of head scratching, I found out what I was doing wrong... I was trying to debug the xpath by printing out the results as in
product_element = Nokogiri.XML(xml).xpath('//root/products/product')
print "product_element is - #{product_element}\n"
that prints out the string version of the element, but instead when I used
product_element = Nokogiri.XML(xml).xpath('//root/products/product')
p product_element
that correctly showed it as a NodeSet.
... This may not be what was happening to you, but

Xpath Axes - how to select child node attribute

I have the following XML:
<ArrayOfStationStatus xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autopagerMatchedRules="1">
<StationStatus ID="20" StatusDetails="To the platform due to planned maintenance work.">
<Station ID="20" Name="Bermondsey"/>
<Status ID="NS" CssClass="Closed" Description="No Step Free Access" IsActive="true">
<StatusType ID="2" Description="Station"/>
</Status>
</StationStatus>
</ArrayOfStationStatus>
And would like to select StationStatus nodes that contain a particular phrase in the Name attribute. It's important that I select SationStatus nodes.
This is the xpath I have come up with but it's not correct:
/ArrayOfStationStatus/StationStatus[contains(lower-case(child::Station/#Name),lower-case('phrase'))]
EDIT::::::::
I just solved it! This is the code I needed:
/ArrayOfStationStatus/StationStatus[child::Station[contains(lower-case(attribute::Name),lower-case("Ac"))]]
Well I managed to solve it people! Here is the solution, in this case I'm looking for the phrase 'Ac' as you can see
/ArrayOfStationStatus/StationStatus[child::Station[contains(lower-case(attribute::Name),lower-case("Ac"))]]
Also remember
lower-case(
is only available in xpath 2.0 (Dimitre Novatchev)

Resources