Copying parent element namespace to child namespace in java - java

I am using java to to generate an xml file. The namespace that is used for parent element has to be copied to the child element as well. I know that the namespaces in the parent node also get reflected to the child nodes, but the external system expects namespaces for both the nodes.
Below is the code I've tried in java. The namespace gets added to the the parent node successfully but not to the child node.
Element root = doc.createElement("ResultSet");
root.setAttribute("xmlns:ns2", "http://www.dummy.com/xsd/tublu/murmur_001");
doc.appendChild(root);
Element child = doc.createElement("Result");
child.setAttribute("xmlns:ns2", "http://www.dummy.com/xsd/tublu/murmur_001");
child.setAttribute("Flag", "true");
child.appendChild(root);
Is there any way I can achieve it using java? Thanks!

Related

adding mutiple namespace for a element in xml file using dom4j

The XML file which need to generate:
<?xml version="1.0" encoding="UTF-8" ?>
<wrapper:MMSRMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wrapper="urn:iso:std:iso:20022:tech:xsd:head.003.001.01" xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:head.003.001.01 MMSR_head.003.001.01_Wrapper.xsd">
<header:AppHdr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:header="urn:iso:std:iso:20022:tech:xsd:head.001.001.01">
<header:Fr>
...
</header:Fr>
</header:AppHdr>
</wrapper:MMSRMessage>
Two namespaces were added for the root element "wrapper:MMSRMessage",It has no problem.
The following is the Java code for it:
Document document = DocumentHelper.createDocument();
Element wrapper = document.addElement("wrapper:MMSRMessage");
wrapper.addNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")
.addNamespace("wrapper", "urn:iso:std:iso:20022:tech:xsd:head.003.001.01")
.addAttribute("xsi:schemaLocation", "urn:iso:std:iso:20022:tech:xsd:head.003.001.01 MMSR_head.003.001.01_Wrapper.xsd");
However, when I add two namespaces for element "header:AppHdr", I get the error message:
Exception in thread "main" org.dom4j.IllegalAddException: No such namespace prefix
using java code:
Element headerApp = wrapper.addElement("header:AppHdr");
headerApp.addNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")
.addNamespace("header", "urn:iso:std:iso:20022:tech:xsd:head.001.001.01");
I also have tried so:
Element headerApp = wrapper.addElement("header:AppHdr","urn:iso:std:iso:20022:tech:xsd:head.001.001.01")
.addNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
in this way the error does not occur, but the namespace "xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" can not be added for the element "header:AppHdr".
That's my first question at Stackoverflow. I hope I can get an answer hier :-)
DOM4J generally offers too many ways to skin the cat. In this area, the confusion is increased because Document#addElement(String, String) and Element#addElement(String, String) do very different validations: In the first case you can add an element with a qualified name without having the prefix bound to a namespace and the element ends up having no namespace (this is a bug). In the second case you must have the prefix bound (correct).
All in all, I reccomend not using qualified element and attribute names (prefix:local-name) if you can avoid it. Instead, strictly separate the local name of the element or attribute and use properly declared Namespace and QName constructs. In your case:
Document document = DocumentHelper.createDocument();
Namespace xsi = Namespace.get("xsi", "http://www.w3.org/2001/XMLSchema-instance");
Namespace wrapper = Namespace.get("wrapper", "urn:iso:std:iso:20022:tech:xsd:head.003.001.01");
Namespace header = Namespace.get("header", "urn:iso:std:iso:20022:tech:xsd:head.001.001.01");
Element wrapperElement = document
.addElement(new QName("MMSRMessage", wrapper))
.addAttribute(new QName("schemaLocation", xsi), "urn:iso:std:iso:20022:tech:xsd:head.003.001.01 MMSR_head.003.001.01_Wrapper.xsd");
Element headerApp = wrapperElement.addElement(new QName("AppHdr", header));
headerApp.addElement(new QName("Fr", header));

How to get Node from XML without considering namespace name in Java?

I am writing a java program in which I am parsing input xml file which looks like this:
...
<ems:DeterminationRequest>
<ems:MessageInformation>
<ns17:MessageID xmlns:ns17="http://www.calheers.ca.gov/EHITSAWSInterfaceCommonSchema">1000225404</ns17:MessageID>
<ns17:MessageTimeStamp xmlns:ns17="http://www.calheers.ca.gov/EHITSAWSInterfaceCommonSchema">2015-07-28T01:17:04</ns17:MessageTimeStamp>
<ns17:SendingSystem xmlns:ns17="http://www.calheers.ca.gov/EHITSAWSInterfaceCommonSchema">CH</ns17:SendingSystem>
<ns17:ReceivingSystem xmlns:ns17="http://www.calheers.ca.gov/EHITSAWSInterfaceCommonSchema">LD</ns17:ReceivingSystem>
<ns17:ServicingFipsCountyCode xmlns:ns17="http://www.calheers.ca.gov/EHITSAWSInterfaceCommonSchema">037</ns17:ServicingFipsCountyCode>
</ems:MessageInformation>
</ems:DeterminationRequest>
...
Now I am trying to get node "ems:MessageInformation" without considering namespace name "ems". So I tried following lines of code:
Document doc = db.parse(new FileInputStream(new File("D:\\test.xml")));
Node element = doc.getDocumentElement().getElementsByTagNameNS("*","MessageInformation").item(0);
System.out.println(element.getNodeName());
But it's giving Null Pointer exception because function is not reading required node. I gone through this link for reference. Can someone tell me what I am doing wrong here?
This is an odd/buggy behaviour in den NodeList implementation returned by
doc.getDocumentElement().getElementsByTagNameNS("*","MessageInformation")
It allows you to access item(0) but returns a null object.
(If you are using a current JDK the NodeList implementation is com.sun.org.apache.xerces.internal.dom.DeepNodeListImpl which lazily loads its items and shows this buggy behaviour).
To prevent the NullPointerException you should first check if the returned NodeList has a length > 0:
NodeList result = doc.getDocumentElement().getElementsByTagNameNS("*","MessageInformation");
if (result.getLength() > 0) {
Node element = (Element)result.item(0);
...
}
Then you need to find out why getElementsByTagNameNS does not return the element.
One possible reason could be that you parsed the document without namespace support. The consequence is that the dom elements don't have namespace information and getElementsByTagNameNS fails.
To turn on namespace support use:
DocumentBuilderFactory.setNamespaceAware(true);
Alternatively without namespace support you could search for
NodeList nl = doc.getDocumentElement().getElementsByTagName("ems:MessageInformation");

DOM Parser wrong childNodes Count

This is strange but let me try my best to put it accross.
I have a XML which i am reading through the normal way from desktop and parsing it through DOM parser.
<?xml version="1.0" encoding="UTF-8"?>
<Abase
xmlns="www.abc.com/Events/Abase.xsd">
<FVer>0</FVer>
<DV>abc App</DV>
<DP>abc Wallet</DP>
<Dversion>11</Dversion>
<sigID>Ss22</sigID>
<activity>Adding New cake</activity>
</Abase>
Reading the XML to get the childs.
Document doc = docBuilder.parse("C://Users//Desktop//abc.xml");
Node root = doc.getElementsByTagName("Abase").item(0);
NodeList listOfNodes = root.getChildNodes(); //Sysout Prints 13
So here my logic works well.When am trying to do by pushing the same XML to a queue and read it and get the child nodes it gives me no. of child nodes is 6.
Document doc=docBuilder.parse(new InputSource(new ByteArrayInputStream(msg.getBytes("UTF-8"))));
Node root = doc.getElementsByTagName("Abase").item(0);
NodeList listOfNodes = root.getChildNodes(); //Sysout Prints 6
this screws my logic of parsing the XML.Can anyone help me out?
UPDATE
Adding sending logic :
javax.jms.TextMessage tmsg = session.createTextMessage();
tmsg.setText(inp);
sender.send(tmsg);
PROBLEM
If i read this xml from desktop it says 13 childs, 6 element node and 7 text nodes.The Common Logic is :
Read all the childs and iterate through list of child items.
If node ISNOT text node get inside if block,add one parent element with two child and append to existing ROOT.Then get NodeName and get TextContext between the element node and push them as setTextContext for both the childs respectively.
So i have a fresh ELEMENT NODE now which have two childs .And as i dont need the already existing element node now which are still the childs of root,Lastly am removing them.
So the above logic is all screwed if i am pushing the XML to queue and areading it for doing the same logic.
OUTPUT XML which is coming good when i read from desktop,but reading from queue is having problem, because it screw the complete tree.
<Abase
xmlns="www.abc.com/Events/Abase.xsd">
<Prop>
<propName>FVer</propName>
<propName>0</propName> //similarly for other nodes
</Prop>
</Abase>
Thanks
Well, there are 13 children if whitespace text nodes are included, but only 6 if whitespace text nodes are dropped. So there's some difference in the way the tree has been built between the two cases, that affects whether whitespace text nodes are retained or not.
The document under "Output XML" means that there is something wrong on the sender side. My guess would by that inp isn't a String but some kind of object and setText(inp) doesn't call inp.toString() but instead triggers some kind of serialization code which produces this odd XML that you're seeing.

Inserting nodes into an existing XML document in GWT client using XMLParser

I have an xml document (using the Document class in the XMLParser library of GWT client) with a format like follows:
<document><node id="0">content</node><node id="1">more content</node></document>
Given an ID, I need to insert a new node immediately after the node with that ID.
So far I've tried using insertBefore (as there is no insertAfter), but I must be using it incorrectly as nothing happens (apart from an UmbrellaException in the js console). I can't find any example usage via search engines.
My attempt is as follows (where n is the node I want to insert after):
Node nNext = n.getNextSibling(); //To get the next sibling to use it with insertBefore
Element newNode = doc.createElement("node");
newNode.appendChild(doc.createTextNode("new content")); //seems to work up until here
n.insertBefore(newNode, nNext); //so this line could be the problem?
insertBefore must be called on the parent node, so:
n.getParentNode().insertBefore(newNode, n.getNextSibling());

How to get elements from XPath in Java

I want to get data from an XPath query:
Element location = (Element) doc.query("//location[location_name='"+ locationName +"']/*").get(0).getDocument().getRootElement();
System.out.println(location.toXML());
Element loc = location.getFirstChildElement("location");
System.out.println(loc.getFirstChildElement("location_name").getValue());
However, no matter what I choose, I always get 1 node (because of .get(0)). I don't know how to select the node which was selected by query.
I found that I should cast the node to Element, (XOM getting attribute from Node?) but the link only shows how to select the first node.
Call getParent() on the first element in the result:
Builder parse = new Builder();
Document xml = parse.build("/var/www/JAVA/toForum.xml");
System.out.println(xml.query("//location[#id=83]/*").get(0).getParent().toXML());
Produces the following output:
<location id="83">
<location_name>name</location_name>
<company_name>company a</company_name>
<machines>
<machine id="12">A</machine>
<machine id="312">B</machine>
</machines>
</location>
The call you make to getDocument() is returning the entirety of the XML document.
The call to query() returns a Nodes object directly containing references to the nodes that you are after.
If you change to
Element location = (Element)doc.query(
"//location[location_name='"+ locationName +"']/*").get(0);
System.out.println(location.getAttribute("location_name").getValue());
it should be ok
EDIT (by extraneon)
Some extra explanation not worthy of an answer by itself:
By doing
Element location =
(Element) doc.query("//location[location_name='"
+ locationName +"']/*").get(0)
.getDocument().getRootElement();
you search through the tree and get the requested node. But then you call getDocument().getRootNode() on the element you want, which will give you the uppermost node of the document.
The above query can thus be simplified to:
Element location = (Element)doc.getRootElement();
which is not wahat you intended.
It's a bit like a bungie jump. You go down to where you need to be (the element) but go immediately back to where you came from (the root element).
It's not clear (at least for me) what actually has to be done. From your query you should get list of nodes matching the given criteria. You will get NodeList and then you can iterate over this NodeList and get content of each node with getNodeValue for example.

Categories

Resources