Java XML importNode function not working as expected - java

My XML looks like this.
I would like to "export" collected_objects into another document. Here is my code-
NodeList nList = reader.getElementsByTagName("collected_objects");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
output.importNode(nNode, true);
}
output refers to the new document I want to write to.
The code is not importing anything from source document. All I get is XML "header" - <?xml version="1.0" encoding="UTF-8" standalone="no"?>
I was expecting that since I've set deep to true, all of the child nodes will be imported but that is not happening.
What am I doing wrong?

importNode only imports the node to the document. You still have to append it somewhere using Node.appendNode(child)

use importNode using this way
Element rootElement = doc.getElementsByTagName("collected_objects");
doc.appendChild(rootElement);
for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {
rootElement.appendChild(doc.importNode(n, true));
}

Related

How to add nodes from another xml using xmlbeans

I am using xmlbeans to generate the xml document, while I need to extract all the children from another xml file and insert them to my current document.
The to_be_add.xml:
<root>
<style>
.....
</style>
<atlas img="styles/jmap.png">
....
</atlas>
.....
</root>
And this xml file does not have a schema so I do not create related java class to map it. You think it as a plain xml file.
I want the style atlas node added. I use the following codes:
XmlObject pointRoot = XmlObject.Factory.parse(Main.class.getResourceAsStream("to_be_added.xml"));
NodeList nodeList = pointRoot.getDomNode().getChildNodes();
Node themeNode = renderthemeDoc.getDomNode();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
themeNode.appendChild(node);
}
Then I got error:
Exception in thread "main"
org.apache.xmlbeans.impl.store.DomImpl$WrongDocumentErr: Child to add
is from another document
And I found this post by searching "child to .... another document": how to add a xml document to another xml document in java which said that the connection between the element and the document has to be broken between the element can be add to other document.
So I try to build the Document object(that is why the variable pointDoc and themeDoc exist):
XmlObject pointRoot = XmlObject.Factory.parse(Main.class.getResourceAsStream("to_be_added.xml"));
Document pointDoc = pointRoot.getDomNode().getOwnerDocument();
System.out.println(pointDoc);
Element element = pointDoc.getDocumentElement();
NodeList nodeList = element.getChildNodes();
Document themeDoc = myCurrentDoc.getDomNode().getOwnerDocument();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
node = themeDoc.importNode(node, true);
themeDoc.appendChild(node);
}
Then I got NullPointerException which said that the pointDoc is null.
That is the whole process how I try to solve this problem. If it is unclear, please tell me, I will update accordingly.
Is it possible to fix it?
Since your other XML file is not mapped to a class, you can use a regular DOM parser to read it and extract its nodes. But using a generic object factory you can still get the nodes:
XmlObject pointRoot = XmlObject.Factory.parse( "<root>\n" +
" <style>\n" +
" </style>\n" +
" <atlas img=\"styles/jmap.png\">\n" +
" </atlas>\n" +
"</root>");
Node pointDoc = pointRoot.getDomNode().getFirstChild();
NodeList nodeList = pointDoc.getChildNodes();
for(int i = 0; i < nodeList.getLength(); i++) {
System.out.println("Node: " + nodeList.item(i).getNodeName());
}
This will print:
Node: #text
Node: style
Node: #text
Node: atlas
Node: #text

How to get XML content as a String

<root>
<h id="1">
<d value="1,2,3,4,5"><open>10:00</open><close>23:00</close></d>
<d value="6"><open>10:00</open><close>2:00</close></d>
<d value="7"><open>10:00</open><close>21:00</close></d>
</h>
<h id="2">
</h>
</root>
Here I have the XML which root has list of <h> tagged nodes. Now I need to break these into parts and set it into different variables (add into a map).
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(new InputSource(new ByteArrayInputStream(data.getBytes("utf-8"))));
NodeList nList = doc.getElementsByTagName("h");
for (int i = 0; i < nList.getLength(); i++)
{
Node nNode = nList.item(i);
System.out.println(nNode.getAttributes().getNamedItem("id") + " " + ?????);
}
what should I call in order to get the value (String value) of a nNode ?
Here is what Im looking for as the asnwer for the above code once some one fills the ????
1 <h id="1"><d value="1,2,3,4,5"><open>10:00</open><close>23:00</close></d><d value="6">open>10:00</open><close>2:00</close></d><d value="7"><open>10:00</open><close>21:00</close></d></h>
2 <h id="2"></h>
And i don't mind having as root element
You can use Node.getTextContent() to conveniently get all the text of a node (gets text of children as well).
See Parsing xml file contents without knowing xml file structure for a short example.
If you're trying to get the value attributes of the d nodes (I can't actually tell, your question is slightly unclear to me), then it would be different -- for that you would iterate through the children of each h node (use getChildNodes() or getFirstChild() + getNextSibling()) then grab their value attributes just as you are getting the id attribute of the h nodes (the above link also shows an example of iterating through child nodes).
Have you tried jDom library? http://www.jdom.org/docs/apidocs/org/jdom2/output/XMLOutputter.html
XMLOutputter outp = new XMLOutputter();
String s = outp.outputString(your_jdom_element);
Have you tried nNode.toString() if you are using Node from javax.xml.soap.Node.
You can use that:
http://docs.oracle.com/javase/7/docs/api/org/w3c/dom/Node.html#getTextContent()
but your sample nNode has other nodes, not just text. It seems you need helper method to construct String from child nodes.
Pass your nNode to nodeToString
XML Node to String in Java

Java parse xml i18n

I'm doing i18n for my web app and I have a list of error messages in an xml file, like this:
<ErrorList>
<Errors culture="en">
<Error id="InvalidBooking">
<Heading1>We are unable to find your booking.</Heading1>
<Heading2></Heading2>
<Description1>Please try again.</Description1>
<Description2>OR</Description2>
<Description3>Seek assistance at the Check-In counter.</Description3>
<Description4></Description4>
</Error>
</Errors>
<Errors culture="zh">
<Error id="InvalidBooking">
<Heading1>我们无法找到您的预订。</Heading1>
<Heading2></Heading2>
<Description1>请再试一次。.</Description1>
<Description2>或</Description2>
<Description3>请联系登机柜台寻求帮助。</Description3>
<Description4></Description4>
</Error>
</Errors>
</ErrorList>
I use the DOM xml parser to load the error messages. Then I get the specific error by matching Error id:
DocumentBuilder builder = DocumentBuilderFactory.newInstance().
newDocumentBuilder();
Document doc = builder.parse(xml);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("Error");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
Error _error = new Error();
_error.setKey(eElement.getAttribute("id"));
_error.setHeading1(eElement.getElementsByTagName("Heading1").item(0).getTextContent());
_error.setHeading2(eElement.getElementsByTagName("Heading2").item(0).getTextContent());
_error.setDescription1(eElement.getElementsByTagName("Description1").item(0).getTextContent());
_error.setDescription2(eElement.getElementsByTagName("Description2").item(0).getTextContent());
_error.setDescription3(eElement.getElementsByTagName("Description3").item(0).getTextContent());
_error.setDescription5(eElement.getElementsByTagName("Description4").item(0).getTextContent());
getErrors().add(_error);
How do I go about specifying the culture id to only load the error messages in that section? For example, when I switch to chinese, it looks up the Errors culture="zh" and only parses in that section?
Thanks.
In your for loop you should be able to get the attribute for the nNode and check it.
if ("zh".equals(nNode.getAttribute("culture"))) {
// do it here...
}

Reading XML in java using DOM

I am new to read XML in Java using DOM. Could someone help me with simple code steps to read this XML in DOM?
Here is my XML:
<DataSet xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:noNamespaceSchemaLocation='datamartschema.1.3.xsd'>
<DataStream title='QUESTIONNAIRE'>
<Record>
<TransactionDate>2014-05-28T14:17:31.2186777-06:00</TransactionDate><SubType>xhaksdj</SubType>
<IntegerValue title='ComponentID'>11111</IntegerValue>
</Record><Record>
<TransactionDate>2014-05-28T14:17:31.2186777-06:00</TransactionDate><SubType>jhgjhg</SubType>
<IntegerValue title='ComponentID'>11111</IntegerValue>
</Record>
</DataStream>
</DataSet>
In this XML I need to read the DataStream value and Record values. My expected output is
DataStream=QUESTIONNAIRE and my records are
<TransactionDate>2014-05-28T14:17:31.2186777-06:00</TransactionDate><SubType>xhaksdj</SubType><IntegerValue title='ComponentID'>11111</IntegerValue><TransactionDate>2014-05-28T14:17:31.2186777-06:00</TransactionDate><SubType>jhgjhg</SubType><IntegerValue title='ComponentID'>11111</IntegerValue>
How can I get this output? I tried myself but I can't get the records output like above. I get the output without Tags which are present in the above output.I am using this line to get the output. But it does not give me correct output. Also, how to read the datastream value from this XML? Kindly help me.
This is my code snippets
NodeList datasetallRecords = indElement.getElementsByTagName("Record");
for (int y = 0; y < datasetallRecords.getLength(); y++) {
Element recordsElement = (Element) datasetallRecords.item(y);
recordXMl = recordXMl + recordsElement.getTextContent();
String d = datasetallRecords.item(y).getTextContent();
if (recordsElement.getTagName().equalsIgnoreCase("SubType")) {
lsDataStreamSubTypes.add(recordsElement.getTextContent());
}
recordCount = y;
}
When you create new instance of builder you can get DataStream
it would be look like this:
Element root = document.getDocumentElement();
NodeList dataStreams = root.getElementsByTagName("DataStream");
then get throw this list and get all info like this:
for (int i = 0; i < dataStreams.lenght(); i++) {
Element dataStream = (Element) dataStreams.item(i);
if (dataStream.getNodeType() == Element.ELEMENT_NODE) {
String title = dataStream.getAttributes()
.getNamedItem("title").getTextContent();
}
}
First you need to create a Node like this
Node nNode = datasetallRecords.item(y);
then an element like this
Element eElement = (Element) nNode;
now you can start taking the values from the element by using the getelementbyid and getnodevalue method.
You're not getting the tags because the call to getTextContent() on the "Record" node will return only the textual content of that node and its descendants.
If you need to nodes as well you'll have to process the XML by hand. Have a look at the DOM tutorial it covers processing a document in DOM mode very well including how to read out element names.

Inserting a node in an xml file

I would like to insert a node in an xml file using Java DOM. I am actually editing a lot of contents of a dummy file in order to mofidy it like the original.
I would want to add an open node and close node in between the following file;
<?xml version="1.0" encoding="utf-8"?>
<Memory xmlns:xyz="http://www.w3.org/2001/XMLSchema-instance"
xmlns:abc="http://www.w3.org/2001/XMLSchema" Derivative="ABC"
xmlns="http://..">
///////////<Address> ///////////(which I would like to insert)
<Block ---------
--------
-------
/>
////////// </Address> /////////(which I would like to insert)
<Parameters Thread ="yyyy" />
</Memory>
I hereby request you to let me know how to I insert -- in between the xml file?
Thanks in advance.!
What I have tried doing is;
Element child = doc.createElement("Address");
child.appendChild(doc.createTextNode("Block"));
root.appendChild(child);
But this gives me an output like;
<Address> Block </Address> and not the way i expect :(
And now, what I have tried is to add these lines;
Element cd = doc.createElement("Address");
Node Block = root.getFirstChild().getNextSibling();
cd.appendChild(Block);
root.insertBefore(cd, root.getFirstChild());
But still, this is not the output which i am looking for. I got this output as
---------
What you want is probably:
Node parent = block.getParentNode()
Node blockRemoved = parent.removeChild(block);
// Create address
parent.appendChild(address);
address.appendChild(blockRemoved);
This is the standard way to re-attach a node in another place under W3C DOM.
Here:
DocumentBuilder b = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = b.parse(...);
// Parent of existing Block elements and new Address elemet
// Might be retrieved differently depending on
// actual structure
Element parent = document.getDocumentElement();
Element address = document.createElement("address");
NodeList nl = parent.getElementsByTagName("Block");
for (int i = 0; i < nl.getLength(); ++i) {
Element block = (Element) nl.item(i);
if (i == 0)
parent.insertBefore(address, block);
parent.removeChild(block);
address.appendChild(block);
}
// UPDATE: how to pretty print
LSSerializer serializer =
((DOMImplementationLS)document.getImplementation()).createLSSerializer();
serializer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
LSOutput output =
((DOMImplementationLS)document.getImplementation()).createLSOutput();
output.setByteStream(System.out);
serializer.write(document, output);
I assume you are using the W3C DOM (e.g. http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html ). If so try
insertBefore(address, block);

Categories