XML and XPath
From Rosetta Code
Programming Task
This is a programming task. It lays out a problem which Rosetta Code users are encouraged to solve, using languages they know.
Perform the following three XPath queries on the XML Document below:
- Retrieve the first "item" element
- Perform an action on each "price" element (print it out)
- Get an array of all the "name" elements
XML Document:
<inventory title="OmniCorp Store #45x10^3">
<section name="health">
<item upc="123456789" stock="12">
<name>Invisibility Cream</name>
<price>14.50</price>
<description>Makes you invisible</description>
</item>
<item upc="445322344" stock="18">
<name>Levitation Salve</name>
<price>23.99</price>
<description>Levitate yourself for up to 3 hours per application</description>
</item>
</section>
<section name="food">
<item upc="485672034" stock="653">
<name>Blork and Freen Instameal</name>
<price>4.95</price>
<description>A tasty meal in a tablet; just add water</description>
</item>
<item upc="132957764" stock="44">
<name>Grob winglets</name>
<price>3.56</price>
<description>Tender winglets of Grob. Just add water</description>
</item>
</section>
</inventory>
Contents |
[edit] C#
XmlReader XReader;
// Either read the xml from a string ...
XReader = XmlReader.Create(new StringReader("<inventory title=... </inventory>"));
// ... or read it from the file system.
XReader = XmlReader.Create("xmlfile.xml");
// Create a XPathDocument object (which implements the IXPathNavigable interface)
// which is optimized for XPath operation. (very fast).
IXPathNavigable XDocument = new XPathDocument(XReader);
// Create a Navigator to navigate through the document.
XPathNavigator Nav = XDocument.CreateNavigator();
Nav = Nav.SelectSingleNode("//item");
// Move to the first element of the selection. (if available).
if(Nav.MoveToFirst())
{
Console.WriteLine(Nav.OuterXml); // The outer xml of the first item element.
}
// Get an iterator to loop over multiple selected nodes.
XPathNodeIterator Iterator = XDocument.CreateNavigator().Select("//price");
while (Iterator.MoveNext())
{
Console.WriteLine(Iterator.Current.Value);
}
Iterator = XDocument.CreateNavigator().Select("//name");
// Use a generic list.
List<string> NodesValues = new List<string>();
while (Iterator.MoveNext())
{
NodesValues.Add(Iterator.Current.Value);
}
// Convert the generic list to an array and output the count of items.
Console.WriteLine(NodesValues.ToArray().Length);
[edit] ColdFusion
<cfsavecontent variable="xmlString"> <inventory ... </inventory> </cfsavecontent> <cfset xml = xmlParse(xmlString)> <!--- First Task ---> <cfset itemSearch = xmlSearch(xml, "//item")> <!--- item = the first Item (xml element object) ---> <cfset item = itemSearch[1]> <!--- Second Task ---> <cfset priceSearch = xmlSearch(xml, "//price")> <!--- loop and print each price ---> <cfloop from="1" to="#arrayLen(priceSearch)#" index="i"> #priceSearch[i].xmlText#<br/> </cfloop> <!--- Third Task ---> <!--- array of all the name elements ---> <cfset names = xmlSearch(xml, "//name")> <!--- visualize the results ---> <cfdump var="#variables#">
[edit] Groovy
def inventory = new XmlSlurper().parseText("<inventory...") //optionally parseText(new File("inv.xml").text)
def firstItem = inventory.section.item[0] //1. first item
inventory.section.item.price.each { println it } //2. print each price
def allNamesArray = inventory.section.item.name.collect {it} //3. collect item names into an array
[edit] JavaScript
Works with: Firefox version 2.0
//create XMLDocument object from file
var xhr = new XMLHttpRequest();
xhr.open('GET', 'file.xml', false);
xhr.send(null);
var doc = xhr.responseXML;
//get first <item> element
var firstItem = doc.evaluate( '//item[1]', doc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue;
alert( firstItem.textContent );
//output contents of <price> elements
var prices = doc.evaluate( '//price', doc, null, XPathResult.ANY_TYPE, null );
for( var price = prices.iterateNext(); price != null; price = prices.iterateNext() ) {
alert( price.textContent );
}
//add <name> elements to array
var names = doc.evaluate( '//name', doc, null, XPathResult.ANY_TYPE, null);
var namesArray = [];
for( var name = names.iterateNext(); name != null; name = names.iterateNext() ) {
namesArray.push( name );
}
alert( namesArray );
Although some browsers support XPath, working with XML is much easier with E4X.
//create XML object from file
var xhr = new XMLHttpRequest();
xhr.open('GET', 'file.xml', false);
xhr.send(null);
var doc = new XML(xhr.responseText);
//get first <item> element
var firstItem = doc..item[0];
alert( firstItem );
//output contents of <price> elements
for each( var price in doc..price ) {
alert( price );
}
//add <name> elements to array
var names = [];
for each( var name in doc..name ) {
names.push( name );
}
alert( names );
[edit] Perl
Library: XML::XPath
use XML::XPath qw();
my $x = XML::XPath->new('<inventory ... </inventory>');
[$x->findnodes('//item[1]')->get_nodelist]->[0];
print $x->findnodes_as_string('//price');
$x->findnodes('//name')->get_nodelist;
[edit] PHP
<?php
//PHP5 only example due to changes in XML extensions between version 4 and 5 (Tested on PHP5.2.0)
$doc = DOMDocument::loadXML('<inventory title="OmniCorp Store #45x10^3">...</inventory>');
//Load from file instead with $doc = DOMDocument::load('filename');
$xpath = new DOMXPath($doc);
/*
1st Task: Retrieve the first "item" element
*/
$nodelist = $xpath->query('//item');
$result = $nodelist->item(0);
/*
2nd task: Perform an action on each "price" element (print it out)
*/
$nodelist = $xpath->query('//price');
for($i = 0; $i < $nodelist->length; $i++)
{
//print each price element in the DOMNodeList instance, $nodelist, as text/xml followed by a newline
print $doc->saveXML($nodelist->item($i))."\n";
}
/*
3rd Task: Get an array of all the "name" elements
*/
$nodelist = $xpath->query('//name');
//our array to hold all the name elements, though in practice you'd probably not need to do this and simply use the DOMNodeList
$result = array();
//a different way of iterating through the DOMNodeList
foreach($nodelist as $node)
{
$result[] = $node;
}
[edit] Python
# Python has basic xml parsing built in
from xml.dom import minidom
xmlfile = file("test3.xml") # load xml document from file
xmldoc = xmldom.parse(xmlfile).documentElement # parse from file stream or...
xmldoc = xmldom.parseString("<inventory title="OmniCorp Store #45x10^3">...</inventory>").documentElement # alternatively, parse a string
# 1st Task: Retrieve the first "item" element
i = xmldoc.getElementsByTagName("item") # get a list of all "item" tags
firstItemElement = i[0] # get the first element
# 2nd task: Perform an action on each "price" element (print it out)
for j in xmldoc.getElementsByTagName("price"): # get a list of all "price" tags
print j.childNodes[0].data # XML Element . TextNode . data of textnode
# 3rd Task: Get an array of all the "name" elements
namesArray = xmldoc.getElementsByTagName("name")
[edit] Ruby
#Example taken from the REXML tutorial (http://www.germane-software.com/software/rexml/docs/tutorial.html) require "rexml/document" include REXML #create the REXML Document from the string (%q is Ruby's multiline string, everything between the two @-characters is the string) doc = Document.new( %q@<inventory title="OmniCorp Store #45x10^3"> ... </inventory> @ ) # The invisibility cream is the first <item> invisibility = XPath.first( doc, "//item" ) # Prints out all of the prices XPath.each( doc, "//price") { |element| puts element.text } # Gets an array of all of the "name" elements in the document. names = XPath.match( doc, "//name" )
[edit] XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="/">
<!-- 1. first item element -->
<xsl:text>
The first item element is</xsl:text>
<xsl:value-of select="//item[1]" />
<!-- 2. Print each price element -->
<xsl:text>
The prices are: </xsl:text>
<xsl:for-each select="//price">
<xsl:text>
</xsl:text>
<xsl:copy-of select="." />
</xsl:for-each>
<!-- 3. Collect all the name elements -->
<xsl:text>
The names are: </xsl:text>
<xsl:copy-of select="//name" />
</xsl:template>
</xsl:stylesheet>
Categories: Programming Tasks | Solutions by Programming Task | C sharp | ColdFusion | Groovy | JavaScript | Perl | XML::XPath | PHP | Python | Ruby | XSLT

