How to retrieve prefixed child elements using JDom - java

I have the following xml snippet from which I am trying to retrieve the first element using JDOM but I am getting nullpointer exception.please help me out if any one knows.
<db1:customer xmlns:db1="http://www.project1.com/db1">
<db1:customerId>22</db1:customerId>
<db1:customerName>PRASAD44</db1:customerName>
<db1:address>Chennai</db1:address>
<db1:email>pkk#gmail.com</db1:email>
<db1:lastUpdate>2014-08-01T00:00:00+05:30</db1:lastUpdate>
<db1:nameDetail>BSM_RESTeter</db1:nameDetail>
<db1:phoneBiz>9916347942</db1:phoneBiz>
<db1:phoneHome>9916347942</db1:phoneHome>
<db1:phoneMobile>944990031</db1:phoneMobile>
<db1:rating>22</db1:rating>
</db1:customer>
here is what I am doing,
SAXBuilder builder = new SAXBuilder();
File xmlFile = new File("CommonFiles/file.xml");
Document doc = (Document) builder.build(xmlFile);
Element rootNode = doc.getRootElement();
Element customerid = rootNode.getChild("sure:customerId");
System.out.println("customerid ======"+customerid);
The print statement displays null.

When dealing with XML containing namespaces, you need to use the Namespace instance that's appropriate for your document. In this case, you have:
<db1:customer xmlns:db1="http://www.project1.com/db1">
The namespace here is http://www.project1.com/db1 and the prefix is db1.
In JDOM you can creaate a reference to a namespace with:
Namespace db1 = Namespace.getNamespace("db1", "http://www.project1.com/db1");
Now, when you retrieve the content in your document, use:
Element customerid = rootNode.getChild("customerId", db1);
Note that you get content using the Namespace object, not the prefix for the element (there is no "db1:" prefix for the "customerId"

Related

How to add new attribute into XML string in JAVA? Condition: based on parent Key and I can use only JAVA internal api if we need to do parse or SAX

I have a following xml string.
<aa>
<bb>
<cc>
<cmd>
<efg sid="C1D7B70D7AF705731B0" mid="C1D7D7AF705731B0" stid="-1" dopt="3">
<pqr>
<dru fo="1" fps="1" nku="WBECDD6CC37656E6C9" tt="1"/>
<dpo drpr="67" dpi="16"/>
<dres >
<dre dreid="BB:8D679D3511D3E4981000E787EC6DE8A4:1:1:0:2:1" fa="1" dpt= "1" o="0"/>
</dres>
</pqr>
</efg>
</cmd>
</cc>
</bb>
</aa>
I need to add "login" attribute inside <efg> tag. So new XML would be
<aa>
<bb>
<cc>
<cmd>
<efg sid="C1D7B70D7AF705731B0" login="sdf34234dfs" mid="C1D7D7AF705731B0" stid="-1" dopt="3">
<pqr>
<dru fo="1" fps="1" nku="WBECDD6CC37656E6C9" tt="1"/>
<dpo drpr="67" dpi="16"/>
<dres >
<dre dreid="BB:8D679D3511D3E4981000E787EC6DE8A4:1:1:0:2:1" fa="1" dpt= "1" o="0"/>
</dres>
</pqr>
</efg>
</cmd>
</cc>
</bb>
</aa>
Condition is:
I can only use inbuilt Java API (java 8) or SAX parser or xmlbuilder
Add condition is based on Parent tag i.e need to check <cmd> then in child need to add <login> because it is not sure always that <efg> tag would always be there with the same name, it could be with any name.
I have tried with DOM parser with following code.
String xml = "xmlString";
//Use method to convert XML string content to XML Document object
Document doc = convertStringToXML( xml );
doc.getDocumentElement().normalize();
Node m = doc.getElementsByTagName("cmd").item(0).getFirstChild();
Attr login = doc.createAttribute("login");
login.setValue("123567");
m.appendChild(login);
However, I am getting following error in my last line of code.
Exception in thread "main" org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
Please anyone suggest me, how to add new attribute login into based on my condition no 2.
NodeList nodeList = doc.getElementsByTagName("cmd");
//Check <cmd> tag is present and then check <cmd> tag has child nodes
if (nodeList != null && nodeList.item(0).hasChildNodes()) {
//Get first child node of <cmd> xml tag
String nodeName = doc.getElementsByTagName("cmd").item(0).getFirstChild().getNodeName();
NodeList childNodeList = doc.getElementsByTagName(nodeName);
Element el = (Element) childNodeList.item(0);
//set pgd_login attribute with respective value
el.setAttribute("login", "xyz");
//Convert back into xml string from Document
xml = XMLHelpers.TransformDOMDocumentToString(doc);
}

CreateTextNode escape characters in large text string

charactersI am trying to include the correct characters in an XML document text node:
Element request = doc.createElement("requestnode");
request.appendChild(doc.createTextNode(xml));
rootElement.appendChild(request);
The xml string is a segment of a large xml file which I have read in:
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("rootnode");
doc.appendChild(rootElement);
<firstname>John</firstname>
<dateOfBirth>28091999</dateOfBirth>
<surname>Doe</surname>
The problem is that passing this into createTextNode is replacing some of the charters:
<firstname>John</firstname>
<dateOfBirth>28091999</dateOfBirth>
<surname>Doe</surname>
Is there any way I can keep the correct characters (< , >) in the textnode. I have read about using importnode but this is not correctly XML, only a segment of a file.
Any help would be greatly appreciated.
EDIT: I need the xml string (which is not fully formatted xml, only a segment of an external xml file) to be in the "request node" as I am building XML to be imported into SOAP UI
You can't pass the element tag and text to the createTextNode() method. You only need to pass the text. You need then to append this text node to an element.
If the source is another XML document, you must extract the text node from an element and insert it in to the other. You can grab a Node (element and text) and try to inserted as a text node in the other. That is why you are seeing all the escape characters.
On the other hand, you can insert this Node into the other XML (if the structure is allowed) and it should be just fine.
In your context, I assume "request" is some sort of Node. The child element of a Node could be another element, text, etc. You have to be very specific.
You can do something like:
Element name = doc.createElement("name");
Element dob = doc.createElement("dateOfBirth");
Element surname = doc.createElement("surname");
name.appendChild( doc.createTextNode("John") );
dob.appendChild( doc.createTextNode("28091999") );
surname.appendChild( doc.createTextNode("Doe") );
Then you can add these element to a parent node:
node.appendChild(name);
node.appendChild(dob);
node.appendChild(surname);
UPDATE: As an alternative, you can open a stream to a document and insert your XML string as a byte stream. Something like this (untested code, but close):
String xmlString = "<firstname>John</firstname><dateOfBirth>28091999</dateOfBirth><surname>Doe</surname>";
DocumentBuilderFactory fac = javax.xml.parsers.DocumentBuilderFactory.newInstance();
DocumentBuilder builder = fac.newDocumentBuilder();
Document newDoc = builder.parse(new ByteArrayInputStream(xmlString.getBytes()));
Element newElem = doc.createElement("whatever");
doc.appendChild(newElem);
Node node = doc.importNode(newDoc.getDocumentElement(), true);
newElem.appendChild(node);
Something like that should do the trick.

add two namespaces into same dom element

I need create a dom document as this:
<namespace:Facturae xmlns:namespace="URI1" xmlns:namespace2="URI2">
//<.......
</namespace:Facturae>
But the following code produce the error:
NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
The code is:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.newDocument();
Element FacturaeElement = document.createElementNS("URI1", "Facturae");
document.appendChild(FacturaeElement);
FacturaeElement.setPrefix("namespace"); //First namespace OK
FacturaeElement.setAttributeNS("URI2", "xmlns:namespace2", "aaa"); //Generate error
//Rest of code
How I can put a second namespace into element??
Searching more information I have reached the solution:
I use the normal setAtribute method (without namespace) indicating the name of the atribute with the xmlns prefix so: "xmlns:namespace2".
Then, I create the sub element with this the namespace and later put the prefix.
Element FacturaeElement = document.createElementNS("URI1", "Facturae");
document.appendChild(FacturaeElement);
FacturaeElement.setPrefix("namespace"); //First namecpace
FacturaeElement.setAttribute("xmlns:namespace2", "URI2"); //second namespace
//I create the subelement with a namespace
Element FileHeaderElement = document.createElementNS("URI2", "FileHeader");
FacturaeElement.appendChild(FileHeaderElement);
FileHeaderElement.setPrefix("namespace2");

How to create an xml with multile root nodes

Example-
<Envision>
<Employee>
<Employee-code>Shiva kumar</Employee-code>
<Employee-Name>474</Employee-Name>
</Employee>
<Employee>
<Employee-code>Santhosh Kumar</Employee-code>
<Employee-Name>475</Employee-Name>
</Employee>
</Envision>
I want to create an xml file as shown above xml.But i am able to do only this -
<Employee>
<Employee-code>Shiva kumar</Employee-code>
<Employee-name>474</Employee-name>
<Employee>
</Envision>
by following code-
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document doc=builder.newDocument();
Element root=doc.createElement("Envision");
doc.appendChild(root);
Element ele=doc.createElement("Employee_Name");
ele.appendChild(doc.createTextNode("Shiva Kumar"));
root.appendChild(ele);
ele=doc.createElement("Employee_Code");
ele.appendChild(doc.createTextNode("474"));
root.appendChild(ele);
TransformerFactory transformerFactory =TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
Whenever i want to add second block to that code by appending this below code to above code
after the employee code tag
Element root1=doc.createElement("Envision");
doc.appendChild(root1);
ele=doc.createElement("Employee_Name");
ele.appendChild(doc.createTextNode("Vijay Babu"));
root1.appendChild(ele);
ele=doc.createElement("Employee_Code");
ele.appendChild(doc.createTextNode(""));
root1.appendChild(ele);
Then i am gettting an Error message like "Creation of the node is not permitted".Please help me in this case
You can't create a second root element - that's simply invalid in XML. But you don't need to. All you need to do is reuse your existing root element. Look at the XML at the top of the question - it only has a single root element, with two Employee elements, right?
It's not clear why you're not creating Employee elements, by the way. You're currently creating Employee_Name and Employee_Code directly under Envision, which doesn't match your sample XML.
I would suggest extracting out the employee-adding code like this:
private static void addEmployee(Document doc, String name, String code) {
Element employee = doc.createElement("Employee");
doc.getDocumentElement().appendChild(employee);
Element nameElement = doc.createElement("Employee_Name");
nameElement.appendChild(doc.createTextNode(name));
employee.appendChild(nameElement);
Element codeElement = doc.createElement("Employee_Code");
codeElement.appendChild(doc.createTextNode(name));
employee.appendChild(codeElement);
}
Then:
Document doc = builder.newDocument();
Element root = doc.createElement("Envision");
doc.appendChild(root);
addEmployee(doc, "Shiva Kumar", "474");
addEmployee(doc, "Vijay Babu", "");
(Alternatively, you could change addEmployee to take the element to append it to.)
XML file can have only one root element. Therefore if you really need more Envision nodes then create one root node for them e.g. ENVISIONS
<ENVISIONS>
<ENVISION>
...
<ENVISION>
<ENVISION>
...
<ENVISION>
</ENVISIONS>
Haven't you forgotten to create EMPLYEE node, have you?
Once you create the root element, you can't create and append another root element to the document.
doc.appendChild(root);
If you want to get that root element to append another employee element to it later you can call the doc.getDocumentElement()
Element root1=doc.getDocumentElement()

Sending a SOAP message

I'm trying to send a SOAP message.
I'm adding manually header to the message, using the next code:
public static void main(String[] args) {
try{
AmdocsServicesServiceagentLocator locator = new AmdocsServicesServiceagentLocator();
PortTypeEndpoint1BindingStub port = new PortTypeEndpoint1BindingStub(new URL("http://srvp7rd-tibco.rnd.local:8025/Process/SoapRequests/Amdocs-Services.serviceagent/PortTypeEndpoint1"),locator);
GetContactRelatedInfo parameters = new GetContactRelatedInfo();
GetContactRelatedInfoRequest request = new GetContactRelatedInfoRequest();
request.setPersonID("6610782925");
request.setPersonIDType("ID number (CPR)");
/* Creating an empty XML Document - We need a document*/
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
Document doc = docBuilder.newDocument();
/* Creating the XML tree */
/* Create the root element and add it to the document */
Element root = doc.createElement("mul:MultiTenant");
doc.appendChild(root);
/* Adding the child to the root */
Element child = doc.createElement("mul:OpCo");
root.appendChild(child);
/* Add text element to the child */
Text text = doc.createTextNode("DENMARK");
child.appendChild(text);
/* Adding the child to the root */
child = doc.createElement("mul:BS");
root.appendChild(child);
/* Add text element to the child */
text = doc.createTextNode("ENV3");
child.appendChild(text);
SOAPHeaderElement element = new SOAPHeaderElement("" ,"soapenv:Header" , doc);
element.setActor(null);
port.setHeader(element);
System.out.println(port.getHeaders()[0]);
port.getContactRelatedInfoOperation(parameters);
} catch (Exception e){
e.printStackTrace();
}
}
But I don't know why, or how I'm ending up with a message including attributes that i didn't wanted.
For example the output message of the current code is:
<soapenv:Header soapenv:mustUnderstand="0" xsi:type="ns1:Document"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns1="http://xml.apache.org/xml-soap">
<mul:MultiTenant xmlns:mul="">
<mul:OpCo xmlns:mul="">DENMARK</mul:OpCo>
<mul:BS xmlns:mul="">ENV3</mul:BS>
</mul:MultiTenant></soapenv:Header>
For example, the xmlns:mul="" attribute in the mul:OpCo tag.
Is there a way to delete that attribute?
Those aren't attributes, those are namespace declarations. You're creating elements with the mul: namespace prefix, and that prefix has to be defined somewhere. Java is adding a default empty declaration (xmlns:mul="") just so that your XML ends up being well-formed - you can't use a prefix without declaring it.
If you don't want those declarations, then remove the mul: prefix, or define it properly elsewhere in the document. You haven't told us what your document should look like, though, so it's hard to advise you how to do that.
You message doesn't have a declaration of the mul namespace. Add it, and the strange xmlns:mul attributes should go away.
Update
Now I understand, you just create a fragment of a soap message. This is just the header and the mul namespace may be declared on the other SOAP-Envelope element.
You need to know the namespace(-name) of mul, double check the full SOAP message in soapUI and double-check the documentation. Then declare the namespace on doc. Later, if the outer element declares mul exactly the same way, the attributes should disappear from the serialized xml.

Categories