Show only games that the "Golfos" team has won - xpath

I would like to know how to ask an XPATH query to solve the question: It shows the games that the "Golfos" team has won.
<?xml version="1.0" encoding="UTF-8"?>
<juego>
<ronda num="1">
<equipo nombre="golfos" puntuacion="22">
</equipo>
<equipo nombre="rios" puntuacion="12">
</equipo>
</ronda>
<ronda num="2">
<equipo nombre="golfos" puntuacion="2">
</equipo>
<equipo nombre="rios" puntuacion="26">
</equipo>
</ronda><ronda num="3">
<equipo nombre="ricos" puntuacion="44">
</equipo>
<equipo nombre="golfos" puntuacion="46">
</equipo>
</ronda>
</juego>

Just use :
//ronda/equipo[#nombre="golfos"][#puntuacion>preceding-sibling::equipo/#puntuacion or #puntuacion>following-sibling::equipo/#puntuacion]
We look for "ronda" nodes where the team Golfos scores more points than the preceding or following team in the same node.
Output : 2

Related

Ruby nokogiri attribute selector in XML file

this is the xml file:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:putResponse
xmlns:ns1="urn:DmsManagerClient">
<result xsi:type="xsd:string">
<?xml version="1.0" encoding="ISO-8859-1"?>
<MESSAGE ID="11c73b9e-687c-4300-baba-b743c26f7c83" TYPE="CUSDMS">
<DELIVERY>
<FROM>
<SENDER>0072000</SENDER>
<SERVICE>eService</SERVICE>
<DATE>2019-03-08T12:27:25</DATE>
</FROM>
<TO>
<DEALER DEALERCODE="0072000" MARKETCODE="1000"/>
</TO>
</DELIVERY>
<CONTENT>
<dms:ComplexResponse ErrorCode="430" ErrorDescription="null : PrivacyUE Mancante" Return="false"
xmlns:dms="http://dmsmanagerservice">
<dms:Element Name="DMSVERSION">2.7</dms:Element>
</dms:ComplexResponse>
</CONTENT>
</MESSAGE>
</result>
</ns1:putResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I am coding with Ruby and I used Nokogiri and the method xpath to extrapole the "CONTENT" of the file
this is the code:
def extrapolate_error(xml)
doc = Nokogiri::XML(File.open(xml))
doc.xpath('//CONTENT')
end
and this is the result:
[#<Nokogiri::XML::Element:0x1c5ba78 name="CONTENT" children=[
#<Nokogiri::XML::Text:0x1c5b940 "\n">,
#<Nokogiri::XML::Element:0x1c5b8bc name="ComplexResponse" namespace=#<Nokogiri::XML::Namespace:0x1c5b88c prefix="dms" href="http://dmsmanagerservice">
attributes=[
#<Nokogiri::XML::Attr:0x1c5b874 name="ErrorCode" value="430">,
#<Nokogiri::XML::Attr:0x1c5b868 name="ErrorDescription" value="null : PrivacyUE Mancante">,
#<Nokogiri::XML::Attr:0x1c5b85c name="Return" value="false">]
children=[#<Nokogiri::XML::Text:0x1c5b118 "\n">,
#<Nokogiri::XML::Element:0x1c5b094 name="Element" namespace=#<Nokogiri::XML::Namespace:0x1c5b88c prefix="dms" href="http://dmsmanagerservice">
attributes=[#<Nokogiri::XML::Attr:0x1c5b058 name="Name" value="DMSVERSION">]
children=[#<Nokogiri::XML::Text:0x1c5abe4 "2.7">]>,
#<Nokogiri::XML::Text:0x1c5aaac "\n">]>,
#<Nokogiri::XML::Text:0x1c5a974 "\n">]>]
Now I need to enter in it and select some attributes.
In the specific I need this:
name="ErrorCode" value="430"
name="ErrorDescription" value="null : PrivacyUE Mancante"
I do not know how to procceed. Can you help me?
The following should work for you assuming the dms namespace is always the same
doc.xpath('//CONTENT/dms:ComplexResponse', dms: 'http://dmsmanagerservice')
.xpath('#ErrorCode | #ErrorDescription')
.each_with_object({}) do |e,obj|
obj[e.name] = e.text
end
#=> {"ErrorCode"=>"430", "ErrorDescription"=>"null : PrivacyUE Mancante"}
You already understand how you got to //CONTENT so from there we use dms:ComplexResponse to navigate deeper but since this is namespaced we have to provide the namespace reference e.g. dms: 'http://dmsmanagerservice'.
Then we select the attributes we are interested in #ErrorCode and #ErrorDescription.
In XPath the pipe | means UNION (think AND) so we want to select both.
Then we are just building a Hash using the name as the key and the text as the value.
XPath Cheatsheet - Useful resource if you need additional reference
Update
You asked about conditionals so this is what I would propose
ndoc = Nokogiri::XML(doc)
namespaces = ndoc.collect_namespaces
response = ndoc.xpath("//CONTENT/dms:ComplexResponse", namespaces)
if response.xpath("self::node()[#ErrorCode != '' and #ErrorDescription != '']").any?
response.xpath("#ErrorCode | #ErrorDescription")
.each_with_object({}) do |e,obj|
obj[e.name] = e.text
end
else
response.xpath('dms:Element/#Name | dms:Element/text()',namespaces)
.each_slice(2)
.map {|s| s.map(&:text)}.to_h
end
This checks to see if there is an ErrorCode and and ErrorDescription if so then Hash as originally proposed. If Not then it returns all the dms:Elements as a Hash so {"DMSVERSION"=>"2.7"} in this case Functional Example

How to use following in Xpath to get siblings in a Tag

I have following Structure: I am trying to build a robust method to extract the elements of FT1_19_0 of the FT1_19 Tag in the order they appear. However
in my results the elements are rearranged. How can i get my result in correct order.
//*/FT1_19/FT1_19_0[contains(../FT1_19_2,'I10') and
not(.=../following::FT1_19/FT1_19_0)]
The Result(Rearranged)
X50.0XXA
M76.891
M17.11
M23.303
<?xml version="1.0" encoding="UTF-8"?>
<root>
<FT1>
<FT1_1>1</FT1_1>
<FT1_4>20180920130000</FT1_4>
<FT1_5>20180924110101</FT1_5>
<FT1_6>CG</FT1_6>
<FT1_7>99203</FT1_7>
<FT1_9/>
<FT1_10>1.00</FT1_10>
<FT1_13>NPI</FT1_13>
<FT1_16>
<FT1_16_1>Gavin, Matthew, MD</FT1_16_1>
<FT1_16_3>22</FT1_16_3>
</FT1_16>
<FT1_19 NO="1">
<FT1_19_0>M76.891</FT1_19_0>
<FT1_19_2>I10</FT1_19_2>
</FT1_19>
<FT1_19 NO="2">
<FT1_19_0>M17.11</FT1_19_0>
<FT1_19_2>I10</FT1_19_2>
</FT1_19>
<FT1_19 NO="3">
<FT1_19_0>M23.303</FT1_19_0>
<FT1_19_2>I10</FT1_19_2>
</FT1_19>
<FT1_19 NO="4">
<FT1_19_0>X50.0XXA</FT1_19_0>
<FT1_19_2>I10</FT1_19_2>
</FT1_19>
</FT1>
</root>
Use this if you are using java:
List<WebElement> list = driver.findElements(By.xpath("//ft1_19//following::ft1_19_0"));
for(WebElement we:list) {
System.out.println(we.getText());
}

How to scrape data from a website using Nokogiri

When I try to scrape the table data from the following link it displays nothing.. `
I write the following code but it gives nothing..I want the table data i.e last Update, weather, temperature from that link which is i given please help me..
url = "http://w1.weather.gov/xml/current_obs/KM89.xml"
docs = Nokogiri::HTML(open(url))
puts docs.css("table")
Go to that page, open your development tools and when you find the response of the request to KM89.xml under Network tab you'll see that it's not returning HTML, but XML like this one:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet href="latest_ob.xsl" type="text/xsl"?>
<current_observation version="1.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.weather.gov/view/current_observation.xsd">
<credit>NOAA's National Weather Service</credit>
<credit_URL>http://weather.gov/</credit_URL>
<image>
<url>http://weather.gov/images/xml_logo.gif</url>
<title>NOAA's National Weather Service</title>
<link>http://weather.gov</link>
</image>
<suggested_pickup>15 minutes after the hour</suggested_pickup>
<suggested_pickup_period>60</suggested_pickup_period>
<location>Dexter B Florence Memorial Field Airport, AR</location>
<station_id>KM89</station_id>
<latitude>34.1</latitude>
<longitude>-93.07</longitude>
<observation_time>Last Updated on Nov 23 2012, 7:56 am CST</observation_time>
<observation_time_rfc822>Fri, 23 Nov 2012 07:56:00 -0600</observation_time_rfc822>
<weather>Light Rain</weather>
<temperature_string>57.0 F (13.8 C)</temperature_string>
<temp_f>57.0</temp_f>
<temp_c>13.8</temp_c>
<relative_humidity>87</relative_humidity>
<wind_string>Northeast at 8.1 MPH (7 KT)</wind_string>
<wind_dir>Northeast</wind_dir>
<wind_degrees>30</wind_degrees>
<wind_mph>8.1</wind_mph>
<wind_kt>7</wind_kt>
<pressure_string>1027.5 mb</pressure_string>
<pressure_mb>1027.5</pressure_mb>
<pressure_in>30.30</pressure_in>
<dewpoint_string>52.9 F (11.6 C)</dewpoint_string>
<dewpoint_f>52.9</dewpoint_f>
<dewpoint_c>11.6</dewpoint_c>
<windchill_string>55 F (13 C)</windchill_string>
<windchill_f>55</windchill_f>
<windchill_c>13</windchill_c>
<visibility_mi>10.00</visibility_mi>
<icon_url_base>http://forecast.weather.gov/images/wtf/small/</icon_url_base>
<two_day_history_url>http://www.weather.gov/data/obhistory/KM89.html</two_day_history_url>
<icon_url_name>ra1.png</icon_url_name>
<ob_url>http://www.weather.gov/data/METAR/KM89.1.txt</ob_url>
<disclaimer_url>http://weather.gov/disclaimer.html</disclaimer_url>
<copyright_url>http://weather.gov/disclaimer.html</copyright_url>
<privacy_policy_url>http://weather.gov/notice.html</privacy_policy_url>
</current_observation>
So you can scrape it like this:
require 'open-uri'
require 'nokogiri'
url = 'http://w1.weather.gov/xml/current_obs/KM89.xml'
doc = Nokogiri::HTML(open(url))
p doc.at_css('station_id').text

Xpath get distinct nodes using preceding-sibling

I need to get distinct values //name() withount distinct-values(//*/name())
I tried do like this, but its dosent work.
//*/name()[.!=//preceding-sibling::*]
How can i repair it?
Using XPath 1.0, to get the distinct values
For name attribute,
/*/*[not(#name = preceding::*/#name)]
For node name,
/*/*[not(name() = preceding::*/name())]
My Sample XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<friend1 name="abc"/>
<friend2 name="def"/>
<friend3 name="abc"/>
<friend1 name="abcd"/>
<friend5 name="abcd"/>
<friend6 name="xyz"/>
<friend8 name="789"/>
<friend0 name="pqr"/>
<friend9 name="lmn"/>
<friend2 name="lmn"/>
<friend5 name="123"/>
<friend7 name="456"/>
<friend12 name="789"/>
</root>

NSXMLDocument, nodesForXPath with namespaces

I want to get a set of elements from a xml-file, but as soon the the elements involve namespaces, it fails.
This is a fragment of the xml file:
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
version="1.0" creator="Groundspeak Pocket Query"
xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.groundspeak.com/cache/1/0 http://www.groundspeak.com/cache/1/0/cache.xsd"
xmlns="http://www.topografix.com/GPX/1/0">
<name>My Finds Pocket Query</name>
<desc>Geocache file generated by Groundspeak</desc>
<author>Groundspeak</author>
<email>contact#groundspeak.com</email>
<time>2010-09-15T16:18:55.9846906Z</time>
<keywords>cache, geocache, groundspeak</keywords>
<bounds minlat="41.89687" minlon="5.561883" maxlat="70.669967" maxlon="25.74735" />
<wpt lat="62.244933" lon="25.74735">
<time>2010-01-11T08:00:00Z</time>
<name>GC22W1T</name>
<desc>Kadonneet ja karanneet by ooti, Traditional Cache (1.5/2)</desc>
<url>http://www.geocaching.com/seek/cache_details.aspx?guid=4af28fe9-401b-44df-b058-5fd5399fc083</url>
<urlname>Kadonneet ja karanneet</urlname>
<sym>Geocache Found</sym>
<type>Geocache|Traditional Cache</type>
<groundspeak:cache id="1521507" available="True" archived="False" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0">
<groundspeak:name>Kadonneet ja karanneet</groundspeak:name>
<groundspeak:placed_by>ooti</groundspeak:placed_by>
<groundspeak:owner id="816431">ooti</groundspeak:owner>
<groundspeak:type>Traditional Cache</groundspeak:type>
<groundspeak:container>Small</groundspeak:container>
<groundspeak:difficulty>1.5</groundspeak:difficulty>
<groundspeak:terrain>2</groundspeak:terrain>
<groundspeak:country>Finland</groundspeak:country>
<groundspeak:state>
</groundspeak:state>
<groundspeak:short_description html="True">
</groundspeak:short_description>
<groundspeak:encoded_hints>
</groundspeak:encoded_hints>
<groundspeak:travelbugs />
</groundspeak:cache>
</wpt>
</gpx>
I want to get all the grounspeak:cache elements, but neither //groundspeak:cache nor //cache seems to return anything.
NSArray *caches = [self.xml nodesForXPath:#"//cache" error:&error];
Any clue?
Edit: Are there any cocoa-based software out there, where I can load my xml and test different xpaths? I'm quite new to objective-c and cocoa, so it would be nice to check that it is really my xpath that is wrong..
This //cache means: a descendant element under no namespace (or empty namespace)
Your groundspeak:cache element is under a namespace URI http://www.groundspeak.com/cache/1/0.
So, if you can't declare a namespace-prefix binding (I think you can't with cocoa...), you could use this XPath expression:
//*[namespace-uri()='http://www.groundspeak.com/cache/1/0' and
local-name()='cache']
If you don't want to be so strict about namespace...
//*[local-name()='cache']
But this last is a bad practice, because you could end up selecting wrong nodes, and because when dealing with XML, your tool should support namespaces.
As proof, this stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:copy-of select="//*[namespace-uri() =
'http://www.groundspeak.com/cache/1/0' and
local-name() = 'cache']"/>
</xsl:template>
</xsl:stylesheet>
Output:
<groundspeak:cache id="1521507" available="True" archived="False"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.topografix.com/GPX/1/0"
xmlns:groundspeak="http://www.groundspeak.com/cache/1/0">
<groundspeak:name>Kadonneet ja karanneet</groundspeak:name>
<groundspeak:placed_by>ooti</groundspeak:placed_by>
<groundspeak:owner id="816431">ooti</groundspeak:owner>
<groundspeak:type>Traditional Cache</groundspeak:type>
<groundspeak:container>Small</groundspeak:container>
<groundspeak:difficulty>1.5</groundspeak:difficulty>
<groundspeak:terrain>2</groundspeak:terrain>
<groundspeak:country>Finland</groundspeak:country>
<groundspeak:state></groundspeak:state>
<groundspeak:short_description html="True"></groundspeak:short_description>
<groundspeak:encoded_hints></groundspeak:encoded_hints>
<groundspeak:travelbugs />
</groundspeak:cache>
You need to add a new namespace attribute to the root node of your document, defining a prefix that you can use when querying the children:
NSXMLDocument *xmldoc = ...
NSXMLElement *namespace = [NSXMLElement namespaceWithName:#"mns" stringValue:#"http://mynamespaceurl.com/mynamespace"];
[xmldoc.rootElement addNamespace:namespace];
then when you query things later, you can use that prefix to refer to the namespace:
NSArray * caches = [xmldoc.rootElement nodesForXPath:#"//mns:caches" error:&error];
//groundspeak:cache should work. You might need a namespace-uri setting as well

Resources