Need of transformer function - java

I am linking to a webservice all works fine. Below is my codes.
private static void printSOAPResponse(SOAPMessage soapResponse) throws Exception {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
Source sourceContent = soapResponse.getSOAPPart().getContent();
System.out.print("\nResponse SOAP Message = \n");
StreamResult result = new StreamResult(System.out);
transformer.transform(sourceContent, result);
}
I am not too sure of the transformerfactory. What I need to do now is to traverse through the results and look for below tag.
<Table diffgr:id="Table1" > and there after there will be few tags in it for e.g.
<rID>1212</rID>
<sNo>15677</sNo>
So what is the best way as some require to covert it into string is that necessary?

Transform to document (unchecked):
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMResult result = new DOMResult();
transformer.transform(sourceContent, result);
Document doc = (Document) result.getNode();
Find in document:
String tag = "Table";
String attr = "diffgr:id";
String attrValue = "Table1";
NodeList list = doc.getElementsByTagName("Table");
Element tableNode = null;
for (int i = 0; i < list.getLength(); i++) {
tableNode = ((Element) list.item(i));
String currentAttrValue = tableNode.getAttribute(attr);
if (attrValue.equals(currentAttrValue)) {
break;
}
}
String childTag1 = "rID";
String childTag2 = "sNo";
Node child1 = (Node) tableNode.getElementsByTagName(childTag1).item(0);
Node child2 = (Node) tableNode.getElementsByTagName(childTag2).item(0);
String rIDValue = child1.getTextContent();
String sNoValue = child1.getTextContent();

You code Transformer transformer = transformerFactory.newTransformer(); is creating an "identity transformer" which copies the input unchanged, so it's not really doing anything useful. What you want here is a real (XSLT) transformer which actually extracts the information you need: something like
<xsl:template match="/">
<xsl:copy-of select="//Table[#diffgr:id='Table1']"/>
</xsl:template>
which you can compile using transformerFactory.newTemplates().

Related

How to modify values of multiple XML tags?

I have been trying to modify values of more than one XML tag in java. So far I am able to get the values of the two nodes that I want to modify but while setting up values it always overrides the first one with the second one.
XML
<driver>
<BirthDate>1977-07-18</BirthDate>
<Age>40</Age>
<Gender>M</Gender>
<PrimaryResidence>OwnCondo</PrimaryResidence>
</driver>
I am trying to change Gender and PrimaryResidence tags.
Code
// Modifies multiple XML nodes
public static String changeCoreDiscountType(String reqXML) {
Document document = null;
String updatedXML = null;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(reqXML));
document = builder.parse(is);
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression expression = xPath.compile("/driver/Gender | /driver/PrimaryResidence");
NodeList nodeList = (NodeList) expression.evaluate(document,XPathConstants.NODESET);
for(int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
node.setTextContent("F");
node.setTextContent("OwnCondo");
String value = node.getTextContent();
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(new StringWriter());
transformer.transform(source, result);
updatedXML = result.getWriter().toString();
} catch (Exception ex) {
ex.printStackTrace();
}
return updatedXML;
}
Any help is appreciated.
You need to check you are updating the correct node first, e.g.
for(int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if(node.getNodeName() == "Gender")
node.setTextContent("F");
if(node.getNodeName() == "PrimaryResidence")
node.setTextContent("OwnCondo");
}
Full Demo

Include delimiter when performing substring operation

How do I include the delimiter when performing a substring operation?
i.e. given the string message which looks like this:
<nutrition>
<daily-values>
<total-fat units="g">65</total-fat>
<saturated-fat units="g">20</saturated-fat>
<cholesterol units="mg">300</cholesterol>
<sodium units="mg">2400</sodium>
<carb units="g">300</carb>
<fiber units="g">25</fiber>
<protein units="g">50</protein>
</daily-values>
</nutrition>
<food>
<name>Avocado Dip</name>
<mfr>Sunnydale</mfr>
<serving units="g">29</serving>
<calories total="110" fat="100"/>
<total-fat>11</total-fat>
<saturated-fat>3</saturated-fat>
<cholesterol>5</cholesterol>
<sodium>210</sodium>
<carb>2</carb>
<fiber>0</fiber>
<protein>1</protein>
<vitamins>
<a>0</a>
<c>0</c>
</vitamins>
<minerals>
<ca>0</ca>
<fe>0</fe>
</minerals>
</food>
and then
message = message.substring(message.indexOf("<food>"), message.indexOf("</food>"));
returns
<food>
<name>Avocado Dip</name>
<mfr>Sunnydale</mfr>
<serving units="g">29</serving>
<calories total="110" fat="100"/>
<total-fat>11</total-fat>
<saturated-fat>3</saturated-fat>
<cholesterol>5</cholesterol>
<sodium>210</sodium>
<carb>2</carb>
<fiber>0</fiber>
<protein>1</protein>
<vitamins>
<a>0</a>
<c>0</c>
</vitamins>
<minerals>
<ca>0</ca>
<fe>0</fe>
</minerals>
How do I get it to keep the last </food> tag given I don't know the surrounding content of the XML file?
Here's a solution using javax.xml. It aims to solve the case when multiple <food> elements are present in the document. In order to handle this case correctly, you need to
deserialize your XML into org.w3c.dom.Document
extract the list of <food> nodes as org.w3c.dom.NodeList
serialize back to String at the end
Here's a simplified example:
private static final String XML =
"<?xml version = \"1.0\" encoding = \"UTF-8\"?>\n"
+ "<message>\n"
+ " <food>\n"
+ " <name>A</name>\n"
+ " </food>\n"
+ " <food>\n"
+ " <name>B</name>\n"
+ " </food>\n"
+ "</message>\n";
#Test
public void xpath() throws Exception {
// Deserialize
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document document;
try (InputStream in = new ByteArrayInputStream(XML.getBytes(StandardCharsets.UTF_8))) {
document = factory.newDocumentBuilder().parse(in);
}
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xPath.compile("//food");
NodeList nodeList = (NodeList) expr.evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
System.out.println(node.getNodeName() + ": " + node.getTextContent().trim());
}
// Serialize
Document exportDoc = factory.newDocumentBuilder().newDocument();
Node exportNode = exportDoc.importNode(nodeList.item(0), true);
exportDoc.appendChild(exportNode);
String content = serialize(exportDoc);
System.out.println(content);
}
private static String serialize(Document doc) throws TransformerException {
DOMSource domSource = new DOMSource(doc);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
// set indent
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(domSource, result);
return writer.toString();
}
The 1st output shows all <food> elements are deserialized correctly:
food: A
food: B
The 2nd output shows the 1st element are serialized back to string:
<food>
<name>A</name>
</food>

How to update multiple nodes in xml in Java

I am trying to update multiple nodes in xml using nodelist. I am able to do it but i don't think my code is efficient. For updating two nodes I am repeating my code twice. I dont know how to loop it. I tried it from for loop, or tried making it an arraylist and everything but it is not working at all.
Here is my code:
String expressionDisclosure = "/DOCUMENT/ishobject/ishfields/ishfield[#name='FHPIDISCLOSURELEVEL']";
String expressionLanguage = "/DOCUMENT/ishobject/ishfields/ishfield[#name='DOC-LANGUAGE']";
String key = "";
String value = "";
try {
DocumentBuilderFactory documentbuilderfactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentbuilder = documentbuilderfactory.newDocumentBuilder();
Document doc = documentbuilder.parse(filepath);
XPath xPath = XPathFactory.newInstance().newXPath();
Node updateNode = null;
NodeList nodelistLanguage = (NodeList) xPath.evaluate(expressionLanguage,
doc.getDocumentElement(), XPathConstants.NODESET);
NodeList nodelistDisclosure = (NodeList) xPath.evaluate(expressionDisclosure,
doc.getDocumentElement(), XPathConstants.NODESET);
key = nodelistLanguage.item(0).getTextContent();
if (key != null) {
value = getHashmap().get(key);
updateNode = nodelistLanguage.item(0);
updateNode.setTextContent(value);
}
key = nodelistDisclosure.item(0).getTextContent();
if (key != null) {
value = getHashmap().get(key);
updateNode = nodelistDisclosure.item(0);
updateNode.setTextContent(value);
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult stream = new StreamResult(new File(filepath));
transformer.transform(source, stream);
} catch (Exception ex) {
ex.printStackTrace();
}
I am updating the node twice. Is this the proper way to do or can it be more efficient?

Adding node to xml using java getting unexpected result?

This is my demo.jsp page
String filename = "TestNode.xml";
ServletContext app = getServletContext();
String projectPath = app.getRealPath("/");
String result = projectPath + filename;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new FileInputStream(new File(result)));
Element rootElement = doc.getDocumentElement();
Element element1 = doc.getDocumentElement();
Element element2 = doc.createElement("hai");
rootElement.appendChild(element2);
Element name = doc.createElement("welcome");
element2.appendChild(name);
element1.appendChild(element2);
DOMSource src = new DOMSource(doc);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = null;
transformer = transformerFactory.newTransformer();
StreamResult rslt = new StreamResult(result);
transformer.transform(src, rslt);
for this i'm getting output as:
<root>
<hai>
<welcome/>
</hai>
</root>
but expected output is:
<root>
<hai>
<welcome>
</welcome>
</hai>
</root>
Where should I change the code to get expected result?
To obtain the output:
<root>
<hai>
<welcome>
</welcome>
</hai>
</root>
Where the <welcome> </welcome> element is actually not empty but contains at least one whitespace character, you need to create a text node and add it as the child of the welcome element:
Element name = doc.createElement("welcome");
Node textNode = doc.createTextNode(" ");
name.appendChild(textNode);
element2.appendChild(name);

Convert an org.w3c.dom.Node into a String

Sorry I'm a Java/XML newbie - and can't seem to figure this one out. It seems it's possible to convert a Document object to a string. However, I want to convert a Node object into a string. I am using org.ccil.cowan.tagsoup Parser for my purpose.
I'm retrieving the Node by something like...
parser = new org.ccil.cowan.tagsoup.Parser()
parser.setFeature(namespaceaware, false)
Transformer transformer = TransformerFactory.newInstance().newTransformer();
DOMResult domResult = new DOMResult();
transformer.transform(new SAXSource(parser, new InputSource(in)), domResult);
Node n = domResult.getNode();
// I'm interested in the first child, so...
Node myNode = n.getChildNodes().item(0);
// convert myNode to string..
// what to do here?
The answer may be obvious, but I can't seem to figure out from the core Java libraries how to achieve this. Any help is much appreciated!
You can use a Transformer (error handling and optional factory configuration omitted for clarity):
Node node = ...;
StringWriter writer = new StringWriter();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(new DOMSource(node), new StreamResult(writer));
String xml = writer.toString();
// Use xml ...
String getNodeString(Node node) {
try {
StringWriter writer = new StringWriter();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(new DOMSource(node), new StreamResult(writer));
String output = writer.toString();
return output.substring(output.indexOf("?>") + 2);//remove <?xml version="1.0" encoding="UTF-8"?>
} catch (TransformerException e) {
e.printStackTrace();
}
return node.getTextContent();
}
This is way to convert Node to html
public static String getInnerHTML(Node node) throws TransformerConfigurationException, TransformerException
{
StringWriter sw = new StringWriter();
Result result = new StreamResult(sw);
TransformerFactory factory = TransformerFactory.newInstance();
Transformer proc = factory.newTransformer();
proc.setOutputProperty(OutputKeys.METHOD, "html");
for (int i = 0; i < node.getChildNodes().getLength(); i++)
{
proc.transform(new DOMSource(node.getChildNodes().item(i)), result);
}
return sw.toString();
}

Categories

Resources