Sending a SOAP message - java

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.

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);
}

Adding sub-element to element java (DOM)

Essentially, i'm creating an XML document from a file (a database), and then i'm comparing another parsed XML file (with updated information) to the original database, then writing the new information into the database.
I'm using java's org.w3c.dom.
After lots of struggling, i decided to just create a new Document object and will write from there from the oldDocument and newDocument ones i'm comparing the elements in.
The XML doc is in the following format:
<Log>
<File name="something.c">
<Warning file="something.c" line="101" column="23"/>
<Warning file="something.c" line="505" column="71" />
</File>
</Log>
as an example.
How would i go about adding in a new "warning" Element to the "File" without getting the pesky "org.w3c.dom.DOMException: WRONG_DOCUMENT_ERR: A node is used in a different document than the one that created it." exception?
Cutting it down, I have something similar to:
public static Document update(Element databaseRoot, Element newRoot){
Document doc = db.newDocument(); // DocumentBuilder defined previously
Element baseRoot = doc.createElement("Log");
//for each file i have:
Element newFileRoot = doc.createElement("File");
//some for loop that parses through each 'file' and looks at the warnings
//when i come to a new warning to add to the Document:
NodeList newWarnings = newFileToCompare.getChildNodes(); //newFileToCompare comes from the newRoot element
for (int m = 0; m < newWarnings.getLength(); m++){
if(newWarnings.item(m).getNodeType() == Node.ELEMENT_NODE){
Element newWarning = (Element)newWarnings.item(m);
Element newWarningRoot = (Element)newWarning.cloneNode(false);
newFileRoot.appendChild(doc.importNode(newWarningRoot,true)); // this is what crashes
}
}
// for new files i have this which works:
newFileRoot = (Element)newFiles.item(i).cloneNode(true);
baseRoot.appendChild(doc.importNode(newFileRoot,true));
doc.appendChild(baseRoot);
return doc;
}
Any ideas? I'm beating my head against the wall. First time doing this.
Going through with a debugger I verified that the document owners were correct. Using node.getOwnerDocument(), I realized that the newFileRoot was connected to the wrong document earlier when I created it, so I changed
Element newFileRoot = (Element)pastFileToFind.cloneNode(false);
to
Element newFileRoot = (Element)doc.importNode(pastFileToFind.cloneNode(false),true);
since later on when i was trying to add the newWarningRoot to newFileRoot, they had different Documents (newWarningRoot was correct but newFileRoot was connected to the wrong document)

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.

How to retrieve prefixed child elements using JDom

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"

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");

Categories