Im trying to merge & evaluate xml using xpath in Java.
I know its xpath 1.0, and 2.0 added if statements.
Im still trying to resolve the issue, hopefuly with your help.
so, 2 files:
1. data.xml
2. view.xml
view.xml contains attributes with xpath expressions, for example:
<item name="/names/name" .... />
I wish to read the entire view.xml as dom-tree, then select all the attributes with xpath expressions and evaluate them.
in this case, with a data.xml such as:
<names>
<name>Bon</name>
</names>
I expect my resulting dom-tree to be:
<item name="Bon" .... />
so far, that isnt too problematic.
The issue comes where I want to be more demanding, such as "if /names/name="Bon" return "name exists"
so that the result would be
<item name="name exists" .... />
What possible ways I have to do such a thing with Java xpath engine (or maybe something else?)
Related
It is easy to parse XML in which tags name are fixed. In XStream, we can simply use #XStreamAlias("tagname") annotation. But how to parse XML in which tag name is not fixed. Suppose I have following XML :
<result>
<result1>
<fixed1> ... </fixed1>
<fixed2> ... </fixed2>
</result1>
<result2>
<item>
<America>
<name> America </name>
<language> English </language>
</America>
</item>
<item>
<Spain>
<name> Spain </name>
<language> Spanish </language>
</Spain>
</item>
</result2>
</result>
Tag names America and Spain are not fixed and sometimes I may get other tag names like Germany, India, etc.
How to define pojo for tag result2 in such case? Is there a way to tell XStream to accept anything as alias name if tag name is not known before-hand?
if it is ok for you to get the tag from inside the tag itself (field 'name'), using Xpath, you can do:
//result2/*/name/text()
another option could be to use the whole element, like:
//result2/*
or also:
//result2/*/name()
Some technologies (specifically, data binding approaches) are optimized for handling XML whose structure is known at compile time. Others (like DOM and other DOM-like tree models - JDOM, XOM etc) are designed for handling XML whose structure is not known in advance. Use the tool for the job.
XSLT and XQuery try to blend both. In their schema-aware form, they can take advantage of static structure information when it is available. But more usually they are run in "untyped" mode, where there is no a-priori knowledge of element names or structure, and everything is handled as it comes. The XSLT rule-based processing paradigm is particularly well suited to "semi-structured" XML whose content is unpredictable or variable.
I have an issue where I want to store the content of a node I am parsing using the XmlPullParser as a string for later parsing. However I can't see how to do this without iterating over the entire content and creating the string myself by creating the start tags etc.
I have read this question, however it is going about it in exactly the way I want to avoid (preferably).
Here is some example XML below.
<result mime="text/xml">
<array>
<item key="action">
<str>testcustom</str>
</item>
<item key="examplearray">
<array>
<item key="0">
<str>Item 0</str>
</item>
<item key="1">
<str>Item 1</str>
</item>
<item key="2">
<str>Item 2</str>
</item>
</array>
</item>
</array>
</result>
My Question
So in this example, I want to get the contents of the result node as an xml string. I don't want to parse it I just want to store it as String for parsing at a later date.
If anyone has any better ideas please let me know.
The PullParser is not giving u that string. In fact the parser is acting like a point on the current token. In order to have the full content of a node - u would need to parse it. Parsing is then of course changing the position of the parser.
The kxml implementation provides a DOM like implementation which has an Element class. This one is giving handy methods for parsing the current element out of a XmlPullParser and also has a toString implementation.
http://www.kxml.org
I have this job in Talend that is supposed to retrieve a field and loop through it.
My big problem is that the code is looping through the XML fields but it's returning null.
Here is a sample of the XML:
<?xml version="1.0" encoding="ISO-8859-1"?>
<empresas>
<empresa>
<imoveis>
<imovel>
[-- some fields -- ]
<fotos>
<nome id="" order="">photo1</nome>
<nome id="" order=""></nome>
<nome id="" order=""></nome>
<nome id="" order=""></nome>
</fotos>
</imovel>
[ -- other entries here -- ]
</imoveis>
</empresa>
</empresas>
Now using the tExtractXMLField component I am trying to get the "fotos" element.
Here is what I have in the component:
I have tried to change the XPath query and the XPath loop query but the result is either I don't loop through the field or I get the null in the value field in the tMap.
Here is an image of the job:
You can see that I have retrieved 4 items from the XML but what I get is null in the "nome" field. There must be something wrong with the XPath but I can't seem to find the problem :(
Hope someone can help me out. Thanks
Notes: I am using talendv4.1.2 on ubuntu 10.10 64bit
If you want to loop on <nome> nodes your Loop XPath Query has to be
"/empresas/empresa/imoveis/imovel/fotos/nome"
and foto_nome XPath Query something like
"text()"
Take care: I also corrected an error in your XML that could bring issues (</imoveis> missing the "s").
There are two ways to go about it. One way is to use directly XMLinput and the instructions that bluish mentioned.
The other way is to continue on the path that you chose. In the XMLinput, make sure that your Loop XPath query is set to "/empresas/empresa/imoveis/imovel/fotos" and that you pass through the fotos element with the Get Nodes option checked. The XPath Query of your fotos element should be "../fotos" or ".".
Your extractXMLField component looks to be well configured.
Also, I don't know what tSetGlobalVar does in your design, but make sure it doesn't affect the fotos element that you're trying to pass through.
I have made a test job, this will help you definitely. If I'm not wrong you want to get all the "nome" under the "fotos" tag.
Try to change your loop xpath to the top level in the file, "empresas". Sometimes that works for me, also I have seem the "?xml version="1.0" encoding="ISO-8859-1"?" tag cause problems before, you could try to remove that.
Also make sure that the encoding is set correctly in the tFileInputXML.
I think you are confusing reading XML and extracting XML from XML.
Reading XML:
If the part of XML you have provided is the file readed by you tFileInputXML you don't need tExtractXMLField, just configure the tFileInputXML as this:
set the xpath loop to the <nome> elements, like this "//nome"
add 3 columns in the tFileInputXML component id, order and content
get content column with xpath query "."
get id value with xpath query "#id"
get order value with xpath query "#order"
Extracting XML from XML:
That is the goal of the tExtractXMLField component:
It allows to parse XML data contained in a database column or another XML document as if it was itself a data flow.
To put it in a nutshell, tExtractXMLField create a flow of data from a column record containing XML.
It is very useful when parsing soap query result: server reply is usually provided as xml, like this one:
<arg2>
<![CDATA[
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<exportInscriptionEnLigneType>
<date>2015-04-10</date>
<nbDossiers>2</nbDossiers>
<reference>20150410100</reference>
<listeDossiers>
<dossier>
<numOrdre>1</numOrdre>
<identifiantDossier>AAAAA</identifiantDossier>
</dossier>
<dossier>
<numOrdre>2</numOrdre>
<identifiantDossier>BBBBB</identifiantDossier>
</dossier>
</listeDossiers>
</exportInscriptionEnLigneType>
]]>
</arg2>
In XML above, arg2>element contains an XML document that you may need to parse.
tExtractXMLField has been created for this purpose.
I've written a tutorial on how to achieve this work, please have a look here "how to extract xml from xml". It is in french but screenshots may help understanding the few comments provided.
Hope it will help.
Best regards,
My output should be something like this:
<result>
<item>
<id>123</id>
<src>123</src>
<dst>123</dst>
</item>
<item>
<!-- ... -->
</item>
</result>
And the action class would have a method getFoos which returns an array of uniform objects, e. g. like this:
class Foo {
// ...
public long getId() { ... }
// ...
}
I'm using the XSLTResult like this:
<action name="channels" method="loadAll" class="com.econemon.suite.api.impl.FooAction">
<result name="success" type="xslt">
<param name="exposedValue">foos</param>
</result>
</action>
Since I don't want to postprocess the XML, I didn't specify any template, after reading several tutorials that said this would work. Instead, it gives me this error:
javax.xml.transform.TransformerException: Operation not supported. - [unknown location]
So I tried using a template, but it never rendered a list at all. Instead I get
all properties of the beans toString()ed together
empty document
empty <foo /> tag (not <foos />, strangely)
I couldn't find a tutorial that helped me, neither on Beans->XML rendering nor XSLT. One problem is that I have trouble coming up with good search terms: googling "struts xml" and similar returns a huge amount of completely irrelevant links about stuff in struts.xml, excluding "struts.xml" from the results is no good either, because pages I'm looking for would likely have example struts.xml snippets.
I think I wouldn't really need the templates, so if it's possible to do without, great.
Some commenters on this blog post had the same error you mentioned. Maybe on of the posted workaround will help?
http://cse-mjmcl.cse.bris.ac.uk/blog/2007/09/10/1189430125294.html
I have the following xml:
<config xmlns="http://www.someurl.com">
<product>
<brand>
<content />
</brand>
</product>
</config>
I'm reading it nicely into JDOM.
However, when I try to use Jaxen to grab the contents, I can't seem to get anything.
Here's an example of what doesn't seem to work:
XPath xpath = new JDOMXPath("config");
SimpleNamespaceContext namespaceContext = new SimpleNamespaceContext();
namespaceContext.addNamespace("", "http://www.someurl.com");
xpath.setNamespaceContext(namespaceContext);
assert xpath.selectNodes(document).size() > 0 : "should find more than 0";
This assertion always fails.
What am I doing wrong?
You have to assign a prefix. Make that call addNamespace("hopfrog", "http://...");
Then make the XPath ("hopfrog:config");
Keep in mind that the prefixes in XML aren't part of the real data model. The real data model assigns a URL, possibly blank, to each element and attribute. You can use any prefix you want in XPath so long as it's bound to the right URL. Since the URL you want it blank, you bind a prefix to 'blank'.