For the following xml:
<books>
<book>
<author>Peter</author>
<title>Tales from Somewhere</title>
<data>
<version>1</version>
</data>
</book>
<book>
<author>Paul</author>
<title>Tales from Nowhere</title>
<data>
<version>2</version>
</data>
</book>
</books>
How can I get the <version> value of the book author 'Paul' above, using this type of notation for building a Java XPathExpression:
//*[local-name()='books']/*
?
I used the following question as a reference:
Get first child node in XSLT using local-name()
Thanks!
This XPath will get the version of a book where there is at an author element with the value "Paul":
//book[author="Paul"]/data/version
When run against this XML:
<books>
<book>
<author>Peter</author>
<title>Tales from Somewhere</title>
<data>
<version>1</version>
</data>
</book>
<book>
<author>Paul</author>
<title>Tales from Nowhere</title>
<data>
<version>2</version>
</data>
</book>
<book>
<author>Peter</author>
<author>Paul</author>
<title>How to write a book with a friend</title>
<data>
<version>7</version>
</data>
</book>
</books>
You get this result:
<version>1</version>
<version>7</version>
Related
I have around 100 plain xml files with repetetive static values. I would like to change them into dynamic by getting values from .properties file so that i can change that value in one place. Is it possible??
Example of current xmls I have :
<?xml version="1.0"?>
<bookstore>
<book category="children">
<title>Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
</bookstore>
**desired change:**
**prop.properties.com**
bookName=Harry Potter
authorName=J K. Rowling
yearValue=2005
priceValue=29.99
<?xml version="1.0"?>
<bookstore>`enter code here`
//load properies file
<book category="children">
<title>${bookName}</title>
<author>${authorName}</author>
<year>${yearValue}</year>
<price>${priceValue}</price>
</book>
</bookstore>
I need to capture an XML message that is sent as part of a request from SOAPui to Wiremock Server. Upon capturing this file, I would then need to compare it against an XSD file. The hard bit is capturing the XML file, I'm not sure what methods wiremock server has that would enable this.
For example, this is the XML message I want to capture in my java application:
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="children">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="web">
<title lang="en">XQuery Kick Start</title>
<author>James McGovern</author>
<author>Per Bothner</author>
<author>Kurt Cagle</author>
<author>James Linn</author>
<author>Vaidyanathan Nagarajan</author>
<year>2003</year>
<price>49.99</price>
</book>
<book category="web">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
What would I need to capture this?
I have an xml of the following structure:
<Root>
<Sample>
<Materil material_class="book" />
<Book Name="harry" Price="8" />
<Book Name="small things" Price="9" />
<Book Name="snow" Price="10" />
</Sample>
<Commodity>
<Sample>
<Materil material_class="sub" />
<Book Name="sherin" Price="8" />
<Book Name="bigthings" Price="9" />
<Book Name="leopard" Price="10" />
</Sample>
<Commodity>
<Sample>
<Materil material_class="sub" />
<Book Name="azxcv" Price="86" />
<Book Name="ddddd" Price="79" />
<Book Name="qwert" Price="810" />
</Sample>
</Commodity>
<Commodity>
<Sample>
<Materil material_class="subtwo" />
<Book Name="ratnam" Price="86" />
<Book Name="shantharam" Price="99" />
<Book Name="da vinci" Price="10" />
</Sample>
</Commodity>
</Commodity>
</Root>
Is there a way to iterate this xml based on condition like,if the material_class = "sub", iterate the Book tag below that and store the #Name and #Price . If the material_class = "book", iterate the Book tag below that. Also i want to get the length of number of /Root/Commodity/Commodity tags (in this case , it is two). Any help is appreciated. I am new to XPath.
To get the Book #Name and #Price for #material_class='sub' or #material_class='book', use this XPATH
/Root[descendant-or-self::Sample or Sample[descendant-or-self::*]]//*[Materil[#material_class='sub' or #material_class='book']]/Book
OR
//Sample[Materil[#material_class='book' or #material_class='sub']]/Book
After loading this XPATH, to print the Name use #Name and Price use #Price
To get the length of number of /Root/Commodity/Commodity tags, XPATH is
/Root/Commodity/Commodity
OR
//Commodity/Commodity
JAVA:
NodeList node = (NodeList) xpath.evaluate("/Root/Commodity/Commodity", xml, XPathConstants.NODESET);
count = node.getLength(); // OUTPUTS: 2
For your information, actually rendering XML through XSLT is much better performance and easier to implement.
<xsl:apply-templates select="//Sample[Materil[#material_class='sub']]/Book"/>
<xsl:apply-templates select="//Sample[Materil[#material_class='book']]/Book"/>
I do not have access to an XSL editor right now, so have not tested the above, but it will give you an idea. Select the Book, and constrain the Materil with the condition you want.
In my case, I have:
<booklist>
<book id="1">
</book>
<book id="2">
</book>
<book id="3">
</book>
......
</booklist>
How can i just return:
<booklist>
<book id="1">
</book>
</booklist>
if I use /booklist/book[#id=1], I can only get
<book id="1">
</book>
But I also need the document element.
Thanks
Rather than selecting the element that you do want, try excluding the elements that you don't want.
If you are just using XPATH, this will select all of the elements except for the book elements who's #id is not equal to 1 (i.e. <booklist><book id="1" /></booklist>).
//*[not(self::book[#id!='1'])]
If you want an XSLT solution, this stylesheet has an empty template that matches all of the <book> elements that do not have #id="1", which prevents them from being copied into the output.
Everything else (document node <booklist> and <book id="1">) will match the identity template, which copies forward.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!--Empty template to prevent book elements
that do not have #id="1" from being
copied into the output -->
<xsl:template match="book[#id!='1']" />
<!--identity template to copy all nodes and attributes to output -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
How can i just return:
< booklist >
< book id=1 >
< /book >
< /booklist >
XPath is a query language. Evaluating an XPath expression cannot change the structure of the XML document.
This is why the answer is: No, with XPath this is not possible!
Whenever you want to transform an XML document (which is exactly the case here), the probably best solution is to use XSLT -- a language which was designed especially for processing and transforming tree-structured data.
Here is a very simple XSLT solution:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="book[not(#id=1)]"/>
</xsl:stylesheet>
When this transformation is applied to the provided XML file, the wanted, correct result is produced:
<booklist>
<book id="1"/>
</booklist>
When you try to select a sub-element, only this will be returned.
I am doing a simple XML parser program.I am running it in command prompt.The program (abc.java) compiles successfully.But it gives following error after running it:
C:\Program Files\Java\jdk1.6.0_13\bin>java abc abc.xml
[Fatal Error] abc.xml:1:8: The
processing instruction target matching
"[xX][mM][ lL]" is not allowed.
Parsing error, line 1, URI
file:/C:/Program%20Files/Java/jdk1.6.0_13/bin/abc.xml
The processing instruction target
matching "[xX][mM][lL]" is not
allowed.
What does it mean? Please help.
Here is my xml file if needed.(abc.xml):
<?xml version="1.0" encoding="UTF-8" ?>
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
</bookstore>
it seems like you have spaces in your xml file before
xml tag
if so, remove them