Java DOM: transforming a node to a root element - java

I have the following XML file (SOAP response) that I'm trying to map to a Java object :
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:AffaireByTiersResponse xmlns:ns2="http://service.hibernate.com/">
<Affaire>
<code_produit>Cred</code_produit>
<id>1</id>
<montant_fin>2000.0</montant_fin>
<id_tier>1</id_tier>
</Affaire>
<Affaire>
<code_produit>Cred</code_produit>
<id>2</id>
<montant_fin>25000.0</montant_fin>
<id_tier>1</id_tier>
</Affaire>
</ns2:AffaireByTiersResponse>
</soap:Body>
</soap:Envelope>
in order to marshall the file I need to keep only the tag <AffaireByTiersResponse> as root element and change its name to <Affaires>.
What is the best way to do this?

Extracting the underlying content from the SOAP envelop can be done using javax.xml.soap.MessageFactory.
String example = new String(Files.readAllBytes(Paths.get("input.xml")), StandardCharsets.UTF_8);
SOAPMessage message = MessageFactory.newInstance().createMessage(null,
new ByteArrayInputStream(example.getBytes()));
Document doc = message.getSOAPBody().extractContentAsDocument();
Element root = doc.getDocumentElement();
The root node can then be renamed
doc.renameNode(root, root.getNamespaceURI(), "Affaires");
and this document can then be passed into the JAXB unmarshaller
Unmarshaller unmarshaller = JAXBContext.newInstance(Affaires.class).createUnmarshaller();
Affaires farm = (Affaires) unmarshaller.unmarshal(doc);

Related

Get parameters from soap request

my app receive a soap request; this is an example:
<SOAP-ENV:Body>
<ns1:authorize>
<params>AppSender</params>
<params>url.appsender.local</params>
<params>GET /applic/ HTTP/1.1</params>
<params>2017-01-4T09:38:00.601Z#NCODER08F839F#myapp.sch</params>
<params>/applic/</params>
<params>2.0.00</params>
<params></params>
<params>d1c714fe-cae1-4150-934f-bb3e61ad85f2</params>
<params>Authentication-Instant</params><params>2017-01-</params>
<params>fiscalCode</params><params>NTSDNT80R085454</params>
<params>userName</params><params>user</params>
<params>levelVerification</params><params>10</params>
<params>AuthenticationType</params><params>BASIC</params>
</ns1:authorize>
Can i have an example that i take this request and i set the value of the tag "params" in a JavaBean???
Thank you
You must process the request with some java library for XML processing.
Example:
org.w3c.dom.Document doc = null;
doc = builder.parse(request);
doc.getDocumentElement().normalize();
org.w3c.dom.Node nodeRoot = doc.getFirstChild();
if(nodeRoot.getNodeName().equals("authorize")) {
... doc.getElementsByTagName("params")...;
You can do it with JAXB, here you have more info ...
http://theopentutorials.com/examples/java/jaxb/generate-java-class-from-xml-schema-in-eclipse-ide/

JAXB Unmarshalling an subset of Unknown XML content

I have a requirement to unmarshall a subset of Unknown XML content, with that unmarshalled object, I need modify some contents and re-bind the same XML content(subset) with the Original XML.
Sample Input XML:
<Message>
<x>
</x>
<y>
</y>
<z>
</z>
<!-- Need to unmarshall this content to "Content" - java Object -->
<Content>
<Name>Robin</Name>
<Role>SM</Role>
<Status>Active</Status>
</Content>
.....
</Message>
Need to unmarshall the <Content> tag alone, by keeping the other XML part as same. Need to modify the elements in <Content> tag and bind the modified XML part with the original as shown below:
Expected Output XML:
<Message>
<x>
</x>
<y>
</y>
<z>
</z>
<!-- Need to unmarshall this content to "Content" - java Object -->
<Content>
<Name>Robin_123</Name>
<Role>Senior Member</Role>
<Status>1</Status>
</Content>
.....
</Message>
My Questions:
What is the possible solution for this Requirement ? (Except DOM parsing - as XML contnet is very huge)
Is there any option to do this in JAXB2.0 ?
Please provide your suggestions on this.
Consider cutting your source document down to size using the StAX API.
For the given sample, this code creates a DOM document with a root element of the Content element:
class ContentFinder implements StreamFilter {
private boolean capture = false;
#Override public boolean accept(XMLStreamReader xml) {
if (xml.isStartElement() && "Content".equals(xml.getLocalName())) {
capture = true;
} else if (xml.isEndElement() && "Content".equals(xml.getLocalName())) {
capture = false;
return true;
}
return capture;
}
}
XMLInputFactory inFactory = XMLInputFactory.newFactory();
XMLStreamReader reader = inFactory.createXMLStreamReader(inputStream);
reader = inFactory.createFilteredReader(reader, new ContentFinder());
Source src = new StAXSource(reader);
DOMResult res = new DOMResult();
TransformerFactory.newInstance().newTransformer().transform(src, res);
Document doc = (Document) res.getNode();
This can then be passed to JAXB as a DOMSource.
Similar techniques can be used when rewriting the XML on output.
JAXB doesn't seem to accept a StreamSource directly, at least in the Oracle 1.7 implementation.
You can annotate an Object property on your class with #XmlAnyElement and by default the unmapped content will be captured as a DOM nodes. If you specify a DomHandler on the #XmlAnyElement then you can control the format. Here is a link to an example where the content is kept as a String.
JAXB use String as it is

Soap response iterat in java

I am using java soap request and response in my code. I am getting the request and response properly.
But I am not able to iterate the response
Please see my response and code used to iterate below. Please help me to resolve this issue.
Response
<?xml version="1.0" encoding="utf-16"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetUserResponse xmlns="http://XXXX.com/XXXXXXXX.XXXXXXX.WS">
<GetUserResult>
user
<PersonID>111113</PersonID>
<Username>0987654321</Username>
<Password />
<FwyMember>Y</FwyMember>
<WebMember>Y</WebMember>
<FirstName>Mohamed</FirstName>
<Tier>firstclass</Tier>
<CountryOfResidence>IN</CountryOfResidence>
<PreferencesChanged>false</PreferencesChanged>
<FamilyRelationship />
<Title>Mr</Title>
<MiddleName />
........ continue like this
Java code
SOAPBody responseBody = response.getSOAPBody();
QName bodyName1 = new QName("http://XXXX.com/XXXXXXXX.XXXXXXX.WS","GetUserResponse");
java.util.Iterator iterator = responseBody.getChildElements(bodyName1);
while (iterator.hasNext()) {
SOAPBodyElement responseElement = (SOAPBodyElement)iterator.next();
String val = responseElement.getValue();
System.out.println("The values are "+val);
}
There is only one GetUserResponse element below Body. getChildElements only gets child elements, as opposed to descendant elements. You must first reach GetUserResponse and then iterate over its children.

Parsing XML node's attribute with prefixes - XSTREAM/JAVA

I'm using StaxDriver with XStream and trying to parse this XML:
<cad:MyObj xmlns:cad="namespace" cad:testeId="873" >
<cad:node1>value node 1</cad:node1>
</cad:MyObj>
into an object.
I can parse node1 with the prefix but I don't know how to configure XStream with Stax to use the prefix cad with atributes (testeId).
Here's my conf:
QNameMap qnameMap = new QNameMap();
qnameMap.setDefaultPrefix("cad");
qnameMap.setDefaultNamespace("namespace");
StaxDriver stax = new StaxDriver(qnameMap);
stax.getInputFactory().setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
stax.setRepairingNamespace(true);
stax.setQnameMap(qnameMap);
xstream = new XStream(stax);
xstream.alias("MyObj", MyObj.class);
xstream.useAttributeFor(MyObj.class, "testeId");
I've tried to "cheat" with this:
xstream.aliasField("cad:testeId", ProdutoVersao.class, "testeId");
but didn't work =/
Hope someone know how to do it.
Well. I think there is no solution for this using XStream.
I've changed to JAXB with a namespace prefix mapper:
http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html
Marshaller m = context.createMarshaller();
ProdutoVersaoPrefixMapper mapper = new ProdutoVersaoPrefixMapper();
m.setProperty("com.sun.xml.internal.bind.namespacePrefixMapper", mapper);
With this code the node and his attributes get the prefix.

Efficient way of parsing XML in Java

I have to parse an XML file with following structure:
<root>
<object_1>
<pro1> abc </pro1>
<pro2> pqr </pro2>
<pro3> xyz </pro3>
<children>
<object_a>
<pro1> abc </pro1>
<pro2> pqr </pro2>
<pro3> xyz </pro3>
<children>
.
.
.
</children>
</object_a>
</children>
</object_1>
<object_2>
.
.
.
</object_n>
</root>
Aim is to parse this multilevel nesting. A few classes are defined in Java.
Class Object_1
Class Object_2
.
.
.
Class Object_N
with their respective properties.
The following code is working for me, but then this is not the best way of doing things.
File file = new File(fileName);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(file);
doc.getDocumentElement().normalize();
if(doc ==null) return;
Node node = doc.getFirstChild();
NodeList lst = node.getChildNodes();
Node children = null ;
int len = lst.getLength();
for(int index=0;index<len;index++)
{
Node child = lst.item(index);
String name = child.getNodeName();
if(name=="Name")
name = child.getNodeValue();
else if(name=="Comment")
comment = child.getNodeValue());
else if(name=="children")
children = child;
}
if(children==null) return;
lst = children.getChildNodes();
len = lst.getLength();
Class<?> obj=null;
AbsModel model = null;
for(int index=0;index<len;index++)
{
Node childNode = lst.item(index);
String modelName = childNode.getNodeName();
try {
obj = Class.forName(modelName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if(obj!=null)
model = (AbsModel) obj.newInstance();
else
model = new GenericModel();
model.restoreDefaultPropFromXML(childNode);
addChild(model);
}
}
Is there a better way of parsing this XML.
Consider using JAXB, which is part of Java since version 6. You should be able to parse (“unmarshall”) your XML file into your own classes with almost no code, just adding a few annotations expliciting the mapping between your object structure and your XML structure.
StAX and or JAXB is almost always the way to go.
If the XML is really dynamic (like attributes specify the property name) ie <prop name="property" value="" /> then you will need to use StAX only or live with what JAXB will map it to (a POJO with name and value properties) and post process.
Personally I find combining StAX and JAXB the best. I parse to the elements I want and then use JAXB to turn the element into a POJO.
See Also:
My own utility library that will turn an XML Stream into an iterator of objects.
Parsing very large XML files and marshalling to Java Objects
http://tedone.typepad.com/blog/2011/06/unmarshalling-benchmark-in-java-jaxb-vs-stax-vs-woodstox.html
While JAXB may be the best choice I'd also like to mention jOOX which provides a JQuery-like API and makes working with XML documents really pleasant.

Categories