XML/XPath: Difference between revisions
Add Nimrod |
→{{header|Python}}: add ElementTree and LXML version |
||
Line 1,428: | Line 1,428: | ||
# 3rd Task: Get an array of all the "name" elements |
# 3rd Task: Get an array of all the "name" elements |
||
namesArray = xmldoc.getElementsByTagName("name")</lang> |
namesArray = xmldoc.getElementsByTagName("name")</lang> |
||
In Python 2.5+ you can use ElementTree's limited XPath support |
|||
<lang python> |
|||
import xml.etree.ElementTree as ET |
|||
xml = open('inventory.xml').read() |
|||
doc = ET.fromstring(xml) |
|||
doc = ET.parse('inventory.xml') # or load it directly |
|||
# Return first Item |
|||
item1 = doc.find("section/item") |
|||
# Note, ElementTree's simple XPath does not support //foo or /foo/bar syntax. |
|||
# Print each price |
|||
for p in doc.findall("section/item/price"): |
|||
print "{0:0.2f}".format(float(p.text)) # could raise exception on missing text or invalid float() conversion |
|||
names = doc.findall("section/item/name") # list of names</lang> |
|||
Or, you can install the <tt>lxml</tt> package and get full XPath support |
|||
<lang python> |
|||
from lxml import etree |
|||
xml = open('inventory.xml').read() |
|||
doc = etree.fromstring(xml) |
|||
doc = etree.parse('inventory.xml') # or load it directly |
|||
# Return first item |
|||
item1 = doc.xpath("//section[1]/item[1]") |
|||
# Print each price |
|||
for p in doc.xpath("//price"): |
|||
print "{0:0.2f}".format(float(p.text)) # could raise exception on missing text or invalid float() conversion |
|||
names = doc.xpath("//name") # list of names</lang> |
|||
=={{header|R}}== |
=={{header|R}}== |
Revision as of 17:44, 28 July 2014
You are encouraged to solve this task according to the task description, using any language you may 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"><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> <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> </inventory>
AutoHotkey
With regular expressions <lang AutoHotkey>FileRead, inventory, xmlfile.xml
RegExMatch(inventory, "<item.*?</item>", item1) MsgBox % item1
pos = 1 While, pos := RegExMatch(inventory, "<price>(.*?)</price>", price, pos + 1)
MsgBox % price1
While, pos := RegExMatch(inventory, "<name>.*?</name>", name, pos + 1)
names .= name . "`n"
MsgBox % names</lang>
<lang AutoHotkey>#Include xpath.ahk
xpath_load(doc, "xmlfile.xml")
- Retrieve the first "item" element
MsgBox % xpath(doc, "/inventory/section[1]/item[1]/text()")
- Perform an action on each "price" element (print it out)
prices := xpath(doc, "/inventory/section/item/price/text()") Loop, Parse, prices,`,
reordered .= A_LoopField "`n"
MsgBox % reordered
- Get an array of all the "name" elements
MsgBox % xpath(doc, "/inventory/section/item/name")</lang>
AppleScript
Using System Events
AppleScript has no-built in support for XPath, but it could be used via a 'do shell script' command. Here's a solution using Apple System Events.
<lang AppleScript>set theXMLdata to "<inventory title=\"OmniCorp Store #45x10^3\">
<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> <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>
</inventory>"
on getElementValuesByName(theXML, theNameToFind) set R to {} tell application "System Events" repeat with i in theXML set {theName, theElements} to {i's name, i's XML elements} if (count of theElements) > 0 then set R to R & my getElementValuesByName(theElements, theNameToFind) if theName = theNameToFind then set R to R & i's value end repeat end tell return R end getElementValuesByName
on getBlock(theXML, theItem, theInstance) set text item delimiters to "" repeat with i from 1 to theInstance set {R, blockStart, blockEnd} to {{}, "<" & theItem & space, "</" & theItem & ">"} set x to offset of blockStart in theXML if x = 0 then exit repeat set y to offset of blockEnd in (characters x thru -1 of theXML as string) if y = 0 then exit repeat set R to characters x thru (x + y + (length of blockEnd) - 2) of theXML as string set theXML to characters (y + (length of blockEnd)) thru -1 of theXML as string end repeat return R end getBlock
tell application "System Events" set xmlData to make new XML data with properties {name:"xmldata", text:theXMLdata}
return my getBlock(xmlData's text, "item", 1) -- Solution to part 1 of problem. return my getElementValuesByName(xmlData's contents, "name") -- Solution to part 2 of problem. return my getElementValuesByName(xmlData's contents, "price") -- Solution to part 3 of problem.
end tell</lang>Output for the three results (respectively):<lang AppleScript>"<item upc=\"123456789\" stock=\"12\">
<name>Invisibility Cream</name> <price>14.50</price> <description>Makes you invisible</description> </item>"
{"Invisibility Cream", "Levitation Salve", "Blork and Freen Instameal", "Grob winglets"}
{"14.50", "23.99", "4.95", "3.56"}</lang>
C#
<lang csharp>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);</lang>
C++
<lang cpp>#include <vector>
- include <string>
- include <iostream>
- include <boost/regex.hpp>
- include <algorithm>
- include <iterator>
int main( ) {
const std::string xmltext( "<inventory title=\"OmniCorp Store #45x10^3\">"
"
" "
"
"</inventory>" ) ; std::string::size_type found = xmltext.find( "<item" , 0 ) ; //beginning of first item std::string::size_type foundnext = xmltext.find( "</item>" , found + 5 ) ; //and its end std::cout << "The first item is\n" << xmltext.substr( found + 5 , foundnext - ( found + 5 ) ) << '\n' ; std::string::const_iterator start , end ; start = xmltext.begin( ) ; end = xmltext.end( ) ; boost::match_results<std::string::const_iterator> what ; boost::regex pricefind( "<price>(\\d+\\.?\\d+)</price>" ) ;//this regex finds the prices start = xmltext.begin( ) ; std::cout << "The prices are:\n" ; while ( boost::regex_search( start , end , what , pricefind ) ) { std::string price( what[ 1 ].first , what[ 1 ].second ) ;//find the first price std::cout << price << std::endl ; start = what[ 1 ].second ; //continue search after first price found } start = xmltext.begin( ) ; std::vector<std::string> names ; boost::regex namefind( "<name>(.+?)</name>" ) ; //find characters, be greedy! while ( boost::regex_search ( start , end , what , namefind ) ) { std::string name ( what[ 1 ].first , what[ 1 ].second ) ; names.push_back( name ) ; start = what[ 1 ].second ; } std::cout << "The following name elements were found in the xml string:\n" ; std::copy( names.begin( ) , names.end( ) , std::ostream_iterator<std::string>( std::cout , "\n" )) ; return 0 ;
}</lang>
Caché ObjectScript
<lang cos>Class XML.Inventory [ Abstract ] {
XData XMLData { <inventory title="OmniCorp Store #45x10^3">
<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> <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>
</inventory> }
ClassMethod QueryXMLDoc(Output names As %List) As %Status {
// get xml stream from the 'XData' block contained in this class Set xdata=##class(%Dictionary.CompiledXData).%OpenId($this_"||XMLData",, .sc) If $$$ISERR(sc) Quit sc Set sc=##class(%XML.XPATH.Document).CreateFromStream(xdata.Data, .xdoc) If $$$ISERR(sc) Quit sc // retrieve the first 'item' element Set sc=xdoc.EvaluateExpression("//section[1]", "item[1]", .res) // perform an action on each 'price' element (print it out) Set sc=xdoc.EvaluateExpression("//price", "text()", .res) If $$$ISERR(sc) Quit sc For i=1:1:res.Count() {
If i>1 Write ", " Write res.GetAt(i).Value
} // get an array of all the 'name' elements Set sc=xdoc.EvaluateExpression("//item", "name", .res) If $$$ISERR(sc) Quit sc Set key="" Do {
Set dom=res.GetNext(.key) If '$IsObject(dom) Quit While dom.Read() { If dom.HasValue Set $List(names, key)=dom.Value }
} While key'="" // finished Quit $$$OK
}
}</lang>
- Examples:
USER>Do ##class(XML.Inventory).QueryXMLDoc(.list) 14.50, 23.99, 4.95, 3.56 USER>Write $ListToString(list, ", ") Invisibility Cream, Levitation Salve, Blork and Freen Instameal, Grob winglets
ColdFusion
<lang cfm><cfsavecontent variable="xmlString"> <inventory ... </inventory> </cfsavecontent> <cfset xml = xmlParse(xmlString)> <cfset itemSearch = xmlSearch(xml, "//item")> <cfset item = itemSearch[1]> <cfset priceSearch = xmlSearch(xml, "//price")> <cfloop from="1" to="#arrayLen(priceSearch)#" index="i">
#priceSearch[i].xmlText#
</cfloop> <cfset names = xmlSearch(xml, "//name")> <cfdump var="#variables#"></lang>
Common Lisp
<lang lisp>(dolist (system '(:xpath :cxml-stp :cxml))
(asdf:oos 'asdf:load-op system))
(defparameter *doc* (cxml:parse-file "xml" (stp:make-builder)))
(xpath:first-node (xpath:evaluate "/inventory/section[1]/item[1]" *doc*))
(xpath:do-node-set (node (xpath:evaluate "/inventory/section/item/price/text()" *doc*))
(format t "~A~%" (stp:data node)))
(defun node-array (node-set)
(coerce (xpath:all-nodes node-set) 'vector))
(node-array
(xpath:evaluate "/inventory/section/item/name" *doc*))</lang>
D
It is important to note that the KXML library currently only supports XPath minimally.
<lang d>import kxml.xml; char[]xmlinput = "<inventory title=\"OmniCorp Store #45x10^3\">
<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> <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>
</inventory> "; void main() {
auto root = readDocument(xmlinput); auto firstitem = root.parseXPath("inventory/section/item")[0]; foreach(price;root.parseXPath("inventory/section/item/price")) { std.stdio.writefln("%s",price.getCData); } auto namearray = root.parseXPath("inventory/section/item/name");
}</lang>
Delphi
<lang Delphi>program XMLXPath;
{$APPTYPE CONSOLE}
uses ActiveX, MSXML;
const
XML = '<inventory title="OmniCorp Store #45x10^3">' + '' + ' <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>' + ' ' + '' + ' <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>' + ' ' + '</inventory>';
var
i: Integer; s: string; lXMLDoc: IXMLDOMDocument2; lNodeList: IXMLDOMNodeList; lNode: IXMLDOMNode; lItemNames: array of string;
begin
CoInitialize(nil); lXMLDoc := CoDOMDocument.Create; lXMLDoc.setProperty('SelectionLanguage', 'XPath'); lXMLDoc.loadXML(XML);
Writeln('First item node:'); lNode := lXMLDoc.selectNodes('//item')[0]; Writeln(lNode.xml); Writeln();
lNodeList := lXMLDoc.selectNodes('//price'); for i := 0 to lNodeList.length - 1 do Writeln('Price = ' + lNodeList[i].text); Writeln();
lNodeList := lXMLDoc.selectNodes('//item/name'); SetLength(lItemNames, lNodeList.length); for i := 0 to lNodeList.length - 1 do lItemNames[i] := lNodeList[i].text; for s in lItemNames do Writeln('Item name = ' + s);
end.</lang>
Output: <lang>First item node: <item upc="123456789" stock="12"> <name>Invisibility Cream</name> <price>14.50</price> <description>Makes you invisible</description> </item>
Price = 14.50 Price = 23.99 Price = 4.95 Price = 3.56
Item name = Invisibility Cream Item name = Levitation Salve Item name = Blork and Freen Instameal Item name = Grob winglets</lang>
E
(currently a very early work in progress/draft library; design comments welcome)
<lang e>? def xml__quasiParser := <import:org.switchb.e.xml.makeXMLQuasiParser>() > def xpath__quasiParser := xml__quasiParser.xPathQuasiParser() > null
? def doc := xml`<inventory title="OmniCorp Store #45x10^3"> >
>
> </inventory>`
- value: xml`...`
? doc[xpath`inventory/section/item`][0]
- value: xml`<item stock="12" upc="123456789">
- <name>Invisibility Cream</name>
- <price>14.50</price>
- <description>Makes you invisible</description>
- </item>`
? for price in doc[xpath`inventory/section/item/price/text()`] { println(price :String) } 14.50 23.99 4.95 3.56
? doc[xpath`inventory/section/item/name`]
- value: [xml`<name>Invisibility Cream</name>`,
- xml`<name>Levitation Salve</name>`,
- xml`<name>Blork and Freen Instameal</name>`,
- xml`<name>Grob winglets</name>`]
</lang>
Erlang
<lang erlang> -module(xml_xpath). -include_lib("xmerl/include/xmerl.hrl").
-export([main/0]).
main() ->
XMLDocument = "<inventory title=\"OmniCorp Store #45x10^3\"><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> <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> </inventory>", {Document,_} = xmerl_scan:string(XMLDocument),
io:format("First item:\n~s\n", [lists:flatten( xmerl:export_simple( [hd(xmerl_xpath:string("//item[1]", Document))], xmerl_xml, [{prolog, ""}]))]), io:format("Prices:\n"), [ io:format("~s\n",[Content#xmlText.value]) || #xmlElement{content = [Content|_]} <- xmerl_xpath:string("//price", Document)],
io:format("Names:\n"), [ Content#xmlText.value || #xmlElement{content = [Content|_]} <- xmerl_xpath:string("//name", Document)].
</lang>
Output:
First item: <item upc="123456789" stock="12"> <name>Invisibility Cream</name> <price>14.50</price> <description>Makes you invisible</description> </item> Prices: 14.50 23.99 4.95 3.56 Names: ["Invisibility Cream","Levitation Salve", "Blork and Freen Instameal","Grob winglets"]
F#
<lang fsharp> open System.IO open System.Xml.XPath
let xml = new StringReader(""" <inventory title="OmniCorp Store #45x10^3">
<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> <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>
</inventory> """)
let nav = XPathDocument(xml).CreateNavigator()
// first "item"; throws if none exists let item = nav.SelectSingleNode(@"//item[1]")
// apply a operation (print text value) to all price elements for price in nav.Select(@"//price") do
printfn "%s" (price.ToString())
// array of all name elements let names = seq { for name in nav.Select(@"//name") do yield name } |> Seq.toArray</lang>
Go
<lang go>package main
import (
"fmt" "os"
"launchpad.net/xmlpath"
)
func main() {
f, err := os.Open("test3.xml") if err != nil { fmt.Println(err) return } n, err := xmlpath.Parse(f) f.Close() if err != nil { fmt.Println(err) return } q1 := xmlpath.MustCompile("//item") if _, ok := q1.String(n); !ok { fmt.Println("no item") } q2 := xmlpath.MustCompile("//price") for it := q2.Iter(n); it.Next(); { fmt.Println(it.Node()) } q3 := xmlpath.MustCompile("//name") names := []*xmlpath.Node{} for it := q3.Iter(n); it.Next(); { names = append(names, it.Node()) } if len(names) == 0 { fmt.Println("no names") }
}</lang>
- Output:
14.50 23.99 4.95 3.56
Groovy
<lang 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</lang>
Haskell
<lang haskell>import Data.List import Control.Arrow import Control.Monad
takeWhileIncl :: (a -> Bool) -> [a] -> [a] takeWhileIncl _ [] = [] takeWhileIncl p (x:xs)
| p x = x : takeWhileIncl p xs | otherwise = [x]
getmultiLineItem n = takeWhileIncl(not.isInfixOf ("</" ++ n)). dropWhile(not.isInfixOf ('<': n)) getsingleLineItems n = map (takeWhile(/='<'). drop 1. dropWhile(/='>')). filter (isInfixOf ('<': n))
main = do
xml <- readFile "./Rosetta/xmlpath.xml" let xmlText = lines xml putStrLn "\n== First item ==\n" mapM_ putStrLn $ head $ unfoldr (Just. liftM2 (id &&&) (\\) (getmultiLineItem "item")) xmlText putStrLn "\n== Prices ==\n" mapM_ putStrLn $ getsingleLineItems "price" xmlText putStrLn "\n== Names ==\n" print $ getsingleLineItems "name" xmlText</lang>
Using the Haskell XML Toolkit (HXT): <lang haskell>{-# LANGUAGE Arrows #-} import Text.XML.HXT.Arrow {- For HXT version >= 9.0, use instead: import Text.XML.HXT.Core -}
deepElem name = deep (isElem >>> hasName name)
process = proc doc -> do
item <- single (deepElem "item") -< doc _ <- listA (arrIO print <<< deepElem "price") -< doc names <- listA (deepElem "name") -< doc returnA -< (item, names)
main = do
[(item, names)] <- runX (readDocument [] "xmlpath.xml" >>> process) print item print names</lang>
HicEst
<lang hicest>CHARACTER xml*1000, output*1000
READ(ClipBoard) xml
EDIT(Text=xml, Right='<item', Right=5, GetPosition=a, Right='</item>', Left, GetPosition=z) WRITE(Text=output) xml( a : z), $CRLF
i = 1
1 EDIT(Text=xml, SetPosition=i, SePaRators='<>', Right='<price>', Word=1, Parse=price, GetPosition=i, ERror=99)
IF(i > 0) THEN WRITE(Text=output, APPend) 'Price element = ', price, $CRLF GOTO 1 ! HicEst does not have a "WHILE" ENDIF
EDIT(Text=xml, SPR='<>', R='<name>', W=1, WordEnd=$CR, APpendTo=output, DO=999) WRITE(ClipBoard) TRIM(output) </lang>
<lang hicest> upc="123456789" stock="12">
<name>Invisibility Cream</name> <price>14.50</price> <description>Makes you invisible</description>
Price element = 14.50 Price element = 23.99 Price element = 4.95 Price element = 3.56 Invisibility Cream
Levitation Salve Blork and Freen Instameal Grob winglets
</lang>
Java
<lang java>import java.io.StringReader; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource;
public class XMLParser { final static String xmlStr = "<inventory title=\"OmniCorp Store #45x10^3\">" + "
" + "
" + "</inventory>";
public static void main(String[] args) { try { Document doc = DocumentBuilderFactory.newInstance() .newDocumentBuilder() .parse(new InputSource(new StringReader(xmlStr))); XPath xpath = XPathFactory.newInstance().newXPath(); // 1 System.out.println(((Node) xpath.evaluate( "/inventory/section/item[1]", doc, XPathConstants.NODE)) .getAttributes().getNamedItem("upc")); // 2, 3 NodeList nodes = (NodeList) xpath.evaluate( "/inventory/section/item/price", doc, XPathConstants.NODESET); for (int i = 0; i < nodes.getLength(); i++) System.out.println(nodes.item(i).getTextContent()); } catch (Exception e) { System.out.println("Error ocurred while parsing XML."); } } }</lang>
JavaScript
<lang javascript>//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 );</lang>
Although some browsers support XPath, working with XML is much easier with E4X.
<lang javascript>//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 );</lang>
Lasso
Lasso has built in support for both XML handling and Xpaths <lang Lasso>// makes extracting attribute values easier define xml_attrmap(in::xml_namedNodeMap_attr) => { local(out = map) with attr in #in do #out->insert(#attr->name = #attr->value) return #out }
local( text = '<inventory title="OmniCorp Store #45x10^3">
<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> <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>
</inventory> ', xml = xml(#text) )
local( items = #xml -> extract('//item'), firstitem = #items -> first, itemattr = xml_attrmap(#firstitem -> attributes), newprices = array )
'First item:
UPC: '
- itemattr -> find('upc')
' (stock: '
- itemattr -> find('stock')
')
'
- firstitem -> extractone('name') -> nodevalue
' ['
- firstitem -> extractone('price') -> nodevalue
'] ('
- firstitem -> extractone('description') -> nodevalue
')
'
with item in #items
let name = #item -> extractone('name') -> nodevalue
let price = #item -> extractone('price') -> nodevalue
do {
#newprices -> insert(#name + ': ' + (decimal(#price) * 1.10) -> asstring(-precision = 2) + ' (' + #price + ')')
}
'Adjusted prices:
'
- newprices -> join('
')
'
'
'Array with all names:
'
- xml -> extract('//name') -> asstaticarray</lang>
Output:
First item: UPC: 123456789 (stock: 12) Invisibility Cream [14.50] (Makes you invisible) Adjusted prices: Invisibility Cream: 15.95 (14.50) Levitation Salve: 26.39 (23.99) Blork and Freen Instameal: 5.45 (4.95) Grob winglets: 3.92 (3.56) Array with all names: staticarray(Invisibility Cream, Levitation Salve, Blork and Freen Instameal, Grob winglets)
Lua
Requires LuaExpat <lang lua>require 'lxp' data = [[<inventory title="OmniCorp Store #45x10^3">
<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> <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>
</inventory>]] local first = true local names, prices = {}, {} p = lxp.new({StartElement = function (parser, name) local a, b, c = parser:pos() --line, offset, pos if name == 'item' and first then print(data:match('.-</item>', c - b + 1)) first = false end if name == 'name' then names[#names+1] = data:match('>(.-)<', c) end if name == 'price' then prices[#prices+1] = data:match('>(.-)<', c) end end})
p:parse(data) p:close()
print('Name: ', table.concat(names, ', ')) print('Price: ', table.concat(prices, ', '))</lang>
Output:
<item upc="123456789" stock="12"> <name>Invisibility Cream</name> <price>14.50</price> <description>Makes you invisible</description> </item> Name: Invisibility Cream, Levitation Salve, Blork and Freen Instameal, Grob winglets Price: 14.50, 23.99, 4.95, 3.56
Mathematica
<lang Mathematica>example = Import["test.txt", "XML"]; Cases[example, XMLElement["item", _ , _] , Infinity] // First Cases[example, XMLElement["price", _, List[n_]] -> n, Infinity] // Column Cases[example, XMLElement["name", _, List[n_]] -> n, Infinity] // Column</lang>
Output:
XMLElement[item,{upc->123456789,stock->12}, {XMLElement[name,{},{Invisibility Cream}],XMLElement[price,{},{14.50}],XMLElement[description,{},{Makes you invisible}]}] 14.50 23.99 4.95 3.56 Invisibility Cream Levitation Salve Blork and Freen Instameal Grob winglets
NetRexx
<lang NetRexx>/* NetRexx */ options replace format comments java crossref symbols binary
import javax.xml.parsers. import javax.xml.xpath. import org.w3c.dom. import org.xml.sax.
xmlStr = -
|| '<inventory title="OmniCorp Store #45x10^3">' - || '' - || ' <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>' - || ' ' - || '' - || ' <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 priwater</description>' - || ' </item>' - || ' ' - || '</inventory>'
expr1 = '/inventory/section/item[1]' expr2 = '/inventory/section/item/price' expr3 = '/inventory/section/item/name' attr1 = 'upc'
do
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(InputSource(StringReader(xmlStr))) xpath = XPathFactory.newInstance().newXPath()
-- Extract attribute from 1st item element say expr1 say " "(Node xpath.evaluate(expr1, doc, XPathConstants.NODE)).getAttributes().getNamedItem(attr1) say
-- Extract and display all price elments nodes = NodeList xpath.evaluate(expr2, doc, XPathConstants.NODESET) say expr2 loop i_ = 0 to nodes.getLength() - 1 say Rexx(nodes.item(i_).getTextContent()).format(10, 2) end i_ say
-- Extract elements and store in an ArrayList nameList = java.util.List nameList = ArrayList() nodes = NodeList xpath.evaluate(expr3, doc, XPathConstants.NODESET) loop i_ = 0 to nodes.getLength() - 1 nameList.add(nodes.item(i_).getTextContent()) end i_
-- display contents of ArrayList say expr3 loop n_ = 0 to nameList.size() - 1 say " "nameList.get(n_) end n_ say
catch ex = Exception
ex.printStackTrace()
end
return </lang> Output:
/inventory/section/item[1] upc="123456789" /inventory/section/item/price 14.50 23.99 4.95 3.56 /inventory/section/item/name Invisibility Cream Levitation Salve Blork and Freen Instameal Grob winglets
Nimrod
<lang nimrod>import xmldom, xmldomparser
let doc = "test3.xml".loadXMLFile.documentElement
- 1st task: retrieve the first "item" element
let i = doc.getElementsByTagName("item")[0]
- 2nd task: perform an action on each "price" element (print it out)
for j in doc.getElementsByTagName "price":
echo j.firstChild.PText.data
- 3rd task: get an array of all the "name" elements
let namesArray = doc.getElementsByTagName "name"</lang>
Objeck
XPath is used to fetch element tags. <lang objeck> use XML;
bundle Default {
class Test { function : Main(args : String[]) ~ Nil { in := String->New(); in->Append("<inventory title=\"OmniCorp Store #45x10^3\">"); in->Append(""); in->Append("<item upc=\"123456789\" stock=\"12\">"); in->Append("<name>Invisibility Cream</name>"); in->Append("<price>14.50</price>"); in->Append("<description>Makes you invisible</description>"); in->Append("</item>"); in->Append("<item upc=\"445322344\" stock=\"18\">"); in->Append("<name>Levitation Salve</name>"); in->Append("<price>23.99</price>"); in->Append("<description>Levitate yourself for up to 3 hours per application</description>"); in->Append("</item>"); in->Append(" "); in->Append(""); in->Append("<item upc=\"485672034\" stock=\"653\">"); in->Append("<name>Blork and Freen Instameal</name>"); in->Append("<price>4.95</price>"); in->Append("<description>A tasty meal in a tablet; just add water</description>"); in->Append("</item>"); in->Append("<item upc=\"132957764\" stock=\"44\">"); in->Append("<name>Grob winglets</name>"); in->Append("<price>3.56</price>"); in->Append("<description>Tender winglets of Grob. Just add water</description>"); in->Append("</item>"); in->Append(" "); in->Append("</inventory>"); parser := XmlParser->New(in); if(parser->Parse()) { # get first item results := parser->FindElements("//inventory/section[1]/item[1]"); if(results <> Nil) { IO.Console->Instance()->Print("items: ")->PrintLine(results->Size()); }; # get all prices results := parser->FindElements("//inventory/section/item/price"); if(results <> Nil) { each(i : results) { element := results->Get(i)->As(XMLElement); element->GetContent()->PrintLine(); }; }; # get names results := parser->FindElements("//inventory/section/item/name"); if(results <> Nil) { IO.Console->Instance()->Print("names: ")->PrintLine(results->Size()); }; }; } }
} </lang>
Oz
We implement a small subset of XPath for this task: <lang oz>declare
[XMLParser] = {Module.link ['x-oz://system/xml/Parser.ozf']}
proc {Main Data} Parser = {New XMLParser.parser init} [Doc] = {Parser parseVS(Data $)}
FirstItem = {XPath Doc [inventory section item]}.1
Prices = {XPath Doc [inventory section item price Text]}
Names = {XPath Doc [inventory section item name]} in {ForAll Prices System.showInfo} end
%% %% Emulation of some XPath functionality: %%
fun {XPath Doc Path} P|Pr = Path in Doc.name = P %% assert {FoldL Pr XPathStep [Doc]} end
fun {XPathStep Elements P} if {IsProcedure P} then {Map Elements P} else {FilteredChildren Elements P} end end
%% A flat list of all Type-children of all Elements. fun {FilteredChildren Elements Type} {Flatten {Map Elements fun {$ E}
{Filter E.children fun {$ X} case X of element(name:!Type ...) then true else false end end}
end}} end
%% PCDATA of an element as a ByteString fun {Text Element} Texts = for Child in Element.children collect:C do
case Child of text(data:BS ...) then {C BS} end end
in {FoldR Texts ByteString.append {ByteString.make nil}} end Data = "<inventory title=\"OmniCorp Store #45x10^3\">" #"" #" <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>" #" " #"" #" <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>" #" " #"</inventory>"
in
{Main Data}</lang>
Perl
<lang perl>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;</lang>
PHP
<lang 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;
}</lang>
PicoLisp
<lang PicoLisp>(load "@lib/xm.l")
(let Sections (body (in "file.xml" (xml)))
(pretty (car (body (car Sections)))) (prinl) (for S Sections (for L (body S) (prinl (car (body L 'price))) ) ) (make (for S Sections (for L (body S) (link (car (body L 'name))) ) ) ) )</lang>
Output:
(item ((upc . "123456789") (stock . "12")) (name NIL "Invisibility Cream") (price NIL "14.50") (description NIL "Makes you invisible") ) 14.50 23.99 4.95 3.56 -> ("Invisibility Cream" "Levitation Salve" "Blork and Freen Instameal" "Grob winglets")
Python
<lang python># Python has basic xml parsing built in
from xml.dom import minidom
xmlfile = file("test3.xml") # load xml document from file xmldoc = minidom.parse(xmlfile).documentElement # parse from file stream or... xmldoc = minidom.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")</lang> In Python 2.5+ you can use ElementTree's limited XPath support <lang python> import xml.etree.ElementTree as ET
xml = open('inventory.xml').read() doc = ET.fromstring(xml)
doc = ET.parse('inventory.xml') # or load it directly
- Return first Item
item1 = doc.find("section/item")
- Note, ElementTree's simple XPath does not support //foo or /foo/bar syntax.
- Print each price
for p in doc.findall("section/item/price"):
print "{0:0.2f}".format(float(p.text)) # could raise exception on missing text or invalid float() conversion
names = doc.findall("section/item/name") # list of names</lang> Or, you can install the lxml package and get full XPath support <lang python> from lxml import etree
xml = open('inventory.xml').read() doc = etree.fromstring(xml)
doc = etree.parse('inventory.xml') # or load it directly
- Return first item
item1 = doc.xpath("//section[1]/item[1]")
- Print each price
for p in doc.xpath("//price"):
print "{0:0.2f}".format(float(p.text)) # could raise exception on missing text or invalid float() conversion
names = doc.xpath("//name") # list of names</lang>
R
<lang R>## Require the XML package you can download from http://www.omegahat.org/RSXML/ library("XML") doc <- xmlInternalTreeParse("test3.xml")
- 1st Task: Retrieve the first "item" element
(firstItemElement <- getNodeSet(doc, "//item")1)
- 2nd task: Perform an action on each "price" element (print it out)
prices <- sapply(getNodeSet(doc, "//price"), xmlValue) for(i in 1:length(prices)) print(prices[i])
- 3rd Task: Get an array of all the "name" elements
(namesArray <- sapply(getNodeSet(doc, "//name"), xmlValue))</lang>
Racket
<lang racket>
- lang at-exp racket
(define input @~a{
<inventory title="OmniCorp Store #45x10^3"><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> <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> </inventory>})
(require xml xml/path)
(define data (xml->xexpr
((eliminate-whitespace '(inventory section item)) (read-xml/element (open-input-string input)))))
- Retrieve the first "item" element
(displayln (xexpr->string (se-path* '(item) data)))
- => <name>Invisibility Cream</name>
- Perform an action on each "price" element (print it out)
(printf "Prices: ~a\n" (string-join (se-path*/list '(item price) data) ", "))
- => Prices
- 14.50, 23.99, 4.95, 3.56
- Get an array of all the "name" elements
(se-path*/list '(item name) data)
- => '("Invisibility Cream" "Levitation Salve" "Blork and Freen Instameal" "Grob winglets")
</lang>
Rascal
<lang rascal>import lang::xml::DOM; import Prelude;
public void get_first_item(loc a){ D = parseXMLDOM(readFile(a)); top-down-break visit(D){ case E:element(_,"item",_): return println(xmlPretty(E)); }; }
public void print_prices(loc a){ D = parseXMLDOM(readFile(a)); for(/element(_,"price",[charData(/str p)]) := D) println(p); }
public list[str] get_names(loc a){ D = parseXMLDOM(readFile(a)); L = []; for(/element(_,"name",[charData(/str n)]) := D) L += n; return L; }</lang> Example output: <lang rascal>rascal>get_first_item(|file:///Users/.../Desktop/xmlpath.xml|) <?xml version="1.0" encoding="UTF-8"?> <item stock="12" upc="123456789">
<name>Invisibility Cream</name> <price>14.50</price> <description>Makes you invisible</description>
</item>
ok
rascal>print_prices(|file:///Users/.../Desktop/xmlpath.xml|) 14.50 23.99 4.95 3.56 ok
rascal>get_names(|file:///Users/.../Desktop/xmlpath.xml|) list[str]: ["Invisibility Cream","Levitation Salve","Blork and Freen Instameal","Grob winglets"]</lang>
Ruby
<lang 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" )</lang>
Scala
The problem description isn't clear on whether what is wanted is the element or the text. Because of that, I'm doing both except for the first problem.
The commands are being inputted into Scala's REPL, to better show the results.
<lang scala>scala> val xml = <inventory title="OmniCorp Store #45x10^3">
|| <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> | || <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> | | </inventory>
xml: scala.xml.Elem = <inventory title="OmniCorp Store #45x10^3">
<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> <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> </inventory>
scala> val firstItem = xml \\ "item" head firstItem: scala.xml.Node = <item upc="123456789" stock="12">
<name>Invisibility Cream</name> <price>14.50</price> <description>Makes you invisible</description> </item>
scala> xml \\ "price" foreach println <price>14.50</price> <price>23.99</price> <price>4.95</price> <price>3.56</price>
scala> xml \\ "price" map (_ text) foreach println 14.50 23.99 4.95 3.56
scala> val elements = xml \\ "name" toArray elements: Array[scala.xml.Node] = Array(<name>Invisibility Cream</name>, <name>Levitation Salve</name>, <name>Blork and Freen Instameal</name>, <name>Grob winglets</name>)
scala> val values = xml \\ "name" map (_ text) toArray values: Array[String] = Array(Invisibility Cream, Levitation Salve, Blork and Freen Instameal, Grob winglets)</lang>
Tcl
<lang tcl># assume $xml holds the XML data package require tdom set doc [dom parse $xml] set root [$doc documentElement]
set allNames [$root selectNodes //name] puts [llength $allNames] ;# ==> 4
set firstItem [lindex [$root selectNodes //item] 0] puts [$firstItem @upc] ;# ==> 123456789
foreach node [$root selectNodes //price] {
puts [$node text]
}</lang>
TUSCRIPT
<lang tuscript> $$ MODE TUSCRIPT,{} MODE DATA $$ XML=* <inventory title="OmniCorp Store #45x10³">
<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> <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>
</inventory> $$ MODE TUSCRIPT
FILE = "test.xml" ERROR/STOP CREATE (file,fdf-o,-std-) FILE/ERASE/UTF8 $FILE = xml
BUILD S_TABLE beg=":<item*>:<name>:<price>:" BUILD S_TABLE end=":</item>:</name>:</price>:" BUILD S_TABLE modifiedbeg=":<name>:<price>:" BUILD S_TABLE modifiedend=":</name>:</price>:" firstitem=names="",countitem=0 ACCESS q: READ/STREAM/UTF8 $FILE s,a/beg+t+e/end LOOP READ/EXIT q IF (a=="<name>") names=APPEND(names,t) IF (a=="<price>") PRINT t IF (a.sw."<item") countitem=1 IF (countitem==1) THEN firstitem=CONCAT(firstitem,a) firstitem=CONCAT(firstitem,t) firstitem=CONCAT(firstitem,e)
IF (e=="</item>") THEN COUNTITEM=0 MODIFY ACCESS q s_TABLE modifiedbeg,-,modifiedend ENDIF
ENDIF ENDLOOP ENDACCESS q ERROR/STOP CLOSE (file) firstitem=EXCHANGE (firstitem,":{2-00} ::") firstitem=INDENT_TAGS (firstitem,-," ") names=SPLIT(names) TRACE *firstitem,names </lang> Output:
14.50 23.99 4.95 3.56 TRACE * 63 -*TUSTEP.EDT firstitem = * 1 = <item upc="123456789" stock="12"> 2 = <name>Invisibility Cream</name> 3 = <price>14.50</price> 4 = <description>Makes you invisible</description> 5 = </item> names = * 1 = Invisibility Cream 2 = Levitation Salve 3 = Blork and Freen Instameal 4 = Grob winglets
Visual Basic .NET
<lang vbnet>Dim first_item = xml.XPathSelectElement("//item") Console.WriteLine(first_item)
For Each price In xml.XPathSelectElements("//price")
Console.WriteLine(price.Value)
Next
Dim names = (From item In xml.XPathSelectElements("//name") Select item.Value).ToArray</lang>
XProc
<lang xml><p:pipeline xmlns:p="http://www.w3.org/ns/xproc"
name="one-two-three" version="1.0"> <p:identity> <p:input port="source"> <p:inline> <root> <first/> <prices/> <names/> </root> </p:inline> </p:input> </p:identity> <p:insert match="/root/first" position="first-child"> <p:input port="insertion" select="(//item)[1]"> <p:pipe port="source" step="one-two-three"/> </p:input> </p:insert> <p:insert match="/root/prices" position="first-child"> <p:input port="insertion" select="//price"> <p:pipe port="source" step="one-two-three"/> </p:input> </p:insert> <p:insert match="/root/names" position="first-child"> <p:input port="insertion" select="//name"> <p:pipe port="source" step="one-two-three"/> </p:input> </p:insert>
</p:pipeline></lang>
XQuery
<lang xquery>(:
1. Retrieve the first "item" element Notice the braces around //item. This evaluates first all item elements and then retrieving the first one. Whithout the braces you get the first item for every section.
- )
let $firstItem := (//item)[1]
(: 2. Perform an action on each "price" element (print it out) :) let $price := //price/data(.)
(: 3. Get an array of all the "name" elements :) let $names := //name
return
<result> <firstItem>{$firstItem}</firstItem> <prices>{$price}</prices> <names>{$names}</names> </result></lang>
Performing this XQuery on the given input document results in <lang xquery><?xml version="1.0" encoding="UTF-8"?> <result>
<firstItem> <item upc="123456789" stock="12"> <name>Invisibility Cream</name> <price>14.50</price> <description>Makes you invisible</description> </item> </firstItem> <prices>14.50 23.99 4.95 3.56</prices> <names> <name>Invisibility Cream</name> <name>Levitation Salve</name> <name>Blork and Freen Instameal</name> <name>Grob winglets</name> </names>
</result></lang>
XSLT
<lang xml><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" /> <xsl:template match="/"> <xsl:text>
The first item element is</xsl:text>
<xsl:value-of select="//item[1]" /> <xsl:text>
The prices are: </xsl:text>
<xsl:for-each select="//price"> <xsl:text> </xsl:text> <xsl:copy-of select="." /> </xsl:for-each> <xsl:text>
The names are: </xsl:text>
<xsl:copy-of select="//name" /> </xsl:template>
</xsl:stylesheet></lang>
- Programming Tasks
- XML
- AutoHotkey
- AHK XPath
- AppleScript
- C sharp
- C++
- C++ examples needing attention
- Examples needing attention
- Caché ObjectScript
- ColdFusion
- Common Lisp
- Plexippus-xpath
- Cxml
- Cxml-stp
- D
- KXML
- Delphi
- E
- E-XML
- Erlang
- Xmerl
- F Sharp
- Go
- Xmlpath
- Groovy
- Haskell
- HicEst
- Java
- JavaScript
- Lasso
- Lua
- Mathematica
- NetRexx
- Nimrod
- Objeck
- Oz
- Perl
- PHP
- PicoLisp
- Python
- R
- XML (R)
- Racket
- Rascal
- Ruby
- REXML
- Scala
- Tcl
- TDOM
- TUSCRIPT
- Visual Basic .NET
- XProc
- XQuery
- XSLT
- Batch File/Omit
- PARI/GP/Omit