I like to set prefix for attribute while creating XML file using Java.
The result that I needed is
<entry gd:etag="*">
<id>Text</id>
</entry>
But I'm getting
<entry etag="*">
<id>Text</id>
</entry>
The code that I have written is
DocumentBuilderFactory docBuildFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuildFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element entry = doc.createElement("entry");
entry.setAttribute("etag","*");
doc.appendChild(entry);
Element id = doc.createElement("id");
id.setTextContent("Text");
entry.appendChild(id);
.....
I have no idea how to set prefix for the attributes. Can someone suggest me how to do this?
You need to set the DocumentBuilderFactory to be namespace aware, and you need to set the namespace for that prefix and use setAttributeNS for an attribute with an XML namespace.
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class Entry {
public static void main(String[] args)
throws IOException, ParserConfigurationException, TransformerException {
String ns = "http://schemas.google.com/g/2005"; // just a guess
DocumentBuilderFactory docBuildFactory = DocumentBuilderFactory.newInstance();
docBuildFactory.setNamespaceAware(true);
DocumentBuilder docBuilder = docBuildFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element entry = doc.createElement("entry");
entry.setAttributeNS(ns, "gd:etag", "*");
doc.appendChild(entry);
Element id = doc.createElement("id");
id.setTextContent("Text");
entry.appendChild(id);
printDocument(doc, System.out);
}
public static void printDocument(Document doc, OutputStream out)
throws IOException, TransformerException {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
transformer.transform(new DOMSource(doc),
new StreamResult(new OutputStreamWriter(out, "UTF-8")));
}
}
Output:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<entry xmlns:gd="http://schemas.google.com/g/2005" gd:etag="*">
<id>Text</id>
</entry>
Replace the namespace URN with the correct one; I just guessed at it based on Googling the gd:etag prefix, which brought up some Google Data API and Google Contacts API stuff.
SimpleXml can do it:
final SimpleXml simple = new SimpleXml();
final Element element =
element("entry").attribute("gd:etag", "*")
.child(element("id").text("Text"));
System.out.println(simple.domToXml(element));
Will output:
<entry gd:etag="*"><id>Text</id></entry>
From maven central:
<dependency>
<groupId>com.github.codemonstur</groupId>
<artifactId>simplexml</artifactId>
<version>1.4.0</version>
</dependency>
Related
In my simple XSLT transformation using standard JDK stuff I am getting unexpected result when using // shortcut.
package my.xslt.test;
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
public class IssuePresenter {
public static void main(String[] args) throws Exception {
StringBuilder xslt = new StringBuilder();
xslt.append("<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
xslt.append(" xmlns:exsl='http://exslt.org/common'");
xslt.append(" exclude-result-prefixes='exsl'");
xslt.append(" version='1.0'>");
xslt.append("<xsl:output indent='yes' omit-xml-declaration='yes'/>");
xslt.append("<xsl:variable name='tree'>");
xslt.append(" <entry level='0'>");
xslt.append(" <entry level='1'/>");
xslt.append(" </entry>");
xslt.append("</xsl:variable>");
xslt.append("<xsl:template match='/'>");
xslt.append(" <a><xsl:copy-of select='exsl:node-set($tree)//entry'/></a>");
xslt.append(" <b><xsl:copy-of select='exsl:node-set($tree)/descendant::entry'/></b>");
xslt.append("</xsl:template>");
xslt.append("</xsl:stylesheet>");
StringWriter writer = new StringWriter();
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Templates templates = transformerFactory.newTemplates(new StreamSource(new StringReader(xslt.toString())));
Transformer transformer = templates.newTransformer();
transformer.transform(new StreamSource(new StringReader("<document/>")), new StreamResult(writer));
System.out.println(writer);
}
}
I expect <a> to be same as <b>. Is it bug or am I missing something?
<a>
<entry level="1"/>
</a><b>
<entry level="0">
<entry level="1"/>
</entry>
<entry level="1"/>
</b>
This issue has been confirmed as a JDK bug, it can be tracked here https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8265134
How do I delete XML tags from XML document in java?
For Example, I have the following XML:
<root>
<item>
<code>100001</code>
<price>456</price>
<name>ABC</name>
</item>
<item>
<code>100002</code>
<price>123</price>
<name>DEF</name>
</item>
<item>
<code>100003</code>
<price>887</price>
<name>XYZ</name>
</item>
</root>
I want to delete the price tag from the XML and produce the XML in the following manner:
<root>
<item>
<code>100001</code>
<name>ABC</name>
</item>
<item>
<code>100002</code>
<name>DEF</name>
</item>
<item>
<code>100003</code>
<name>XYZ</name>
</item>
</root>
Additionally the requirement is such that the XML tags can change as I get this information from a webservice which can change the information it sends.
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.util.ArrayList;
public class JAXBExample {
static Root root = new Root();
public static void main(String[] args) throws JAXBException {
File file = new File("C:\\file.xml");
File file1 = new File("C:\\result.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Root rootEle = (Root) jaxbUnmarshaller.unmarshal(file);
ArrayList<item> itemList =new ArrayList<>();
for (int i = 0; i < rootEle.getItemList().size() ; i++){
item itemLocal = new item();
itemLocal.setCode(rootEle.getItemList().get(i).getCode());
itemLocal.setName(rootEle.getItemList().get(i).getName());
itemList.add(itemLocal);
}
root.setItemList(itemList);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// output pretty printed
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(root, file1);
jaxbMarshaller.marshal(root, System.out);
}
}
Root class:
import org.apache.activemq.kaha.impl.data.Item;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
#XmlRootElement(name = "root")
public class Root {
public ArrayList<item> getItem() {
return itemList;
}
public void setItem(ArrayList<item> item) {
this.itemList = item;
}
private ArrayList<item> itemList;
}
Item calss:
public class item {
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String code;
private String name;
}
I hope this will help.
As commented, consider XSLT that runs the Identity Transform and an empty template on the node you wish to remove. No for loops, if logic, or use of data structures (e.g., arraylist, hashmaps) needed for this solution.
As information, XSLT is a special purpose language (sibling to XPath) designed to transform xml files into other xml, html, even text files (csv/txt). General purpose languages like Java, PHP, Python, and others maintain libraries to run XSLT 1.0 scripts and can even call external dedicated XSLT processors like libxslt/Saxon. Additionally, XSLT scripts are themselves well-formed XML files and can be parsed from file or string for any dynamic needs.
XSLT (save as .xsl script to be parsed from file in Java below)
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<!-- Identity Transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Removes all price tags -->
<xsl:template match="price"/>
</xsl:transform>
Java
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.OutputKeys;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class CourseList {
public static void main(String[] args) throws IOException, URISyntaxException,
SAXException,
ParserConfigurationException,
TransformerException {
// LOAD XML AND XSL DOCUMENTS
String inputXML = "C:\\Path\\To\\Input.xml";
String xslFile = "C:\\Path\\To\\XSLTScript.xsl";
String outputXML = "C:\\Path\\To\\Output.xml";
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse (new File(inputXML));
Source xslt = new StreamSource(new File(xslFile));
// XSLT TRANSFORMATION WITH PRETTY PRINT
TransformerFactory prettyPrint = TransformerFactory.newInstance();
Transformer transformer = prettyPrint.newTransformer(xslt);
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(outputXML));
transformer.transform(source, result);
}
}
I am trying to parse an XML and the code that I use is as follows:
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.StringReader;
public class Main {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:comm3=\"http://www.csapi.org/schema/parlayx/common/v3_1\" xmlns:sms7=\"http://www.csapi.org/schema/parlayx/sms/notification/v3_1/local\">\r\n <SOAP-ENV:Header>\r\n <comm3:NotifySOAPHeader>\r\n <spId>37</spId>\r\n </comm3:NotifySOAPHeader>\r\n </SOAP-ENV:Header>\r\n <SOAP-ENV:Body SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n <sms7:notifySmsDeliveryReceipt>\r\n <sms7:correlator>123</sms7:correlator>\r\n <sms7:deliveryStatus>\r\n <address>tel:959257118550</address>\r\n <deliveryStatus>DeliveredToTerminal</deliveryStatus>\r\n </sms7:deliveryStatus>\r\n </sms7:notifySmsDeliveryReceipt>\r\n </SOAP-ENV:Body>\r\n</SOAP-ENV:Envelope>\r\n";
System.out.println("xml:");
System.out.println(xml);
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder loader = factory.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xml));
Document doc = loader.parse(is);
NodeList nodeList = doc.getElementsByTagNameNS("http://www.csapi.org/schema/parlayx/sms/notification/v3_1/local", "correlator");
Element correlatorElement = (Element) nodeList.item(0);
System.out.println(correlatorElement);
NodeList addressNodeList = doc.getElementsByTagName("address");
System.out.println(addressNodeList.item(0));
}
}
Without throwing any exception, the code prints the results but what we get is not what we would expect.
xml:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:comm3="http://www.csapi.org/schema/parlayx/common/v3_1" xmlns:sms7="http://www.csapi.org/schema/parlayx/sms/notification/v3_1/local">
<SOAP-ENV:Header>
<comm3:NotifySOAPHeader>
<spId>37</spId>
</comm3:NotifySOAPHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<sms7:notifySmsDeliveryReceipt>
<sms7:correlator>123</sms7:correlator>
<sms7:deliveryStatus>
<address>tel:959257118550</address>
<deliveryStatus>DeliveredToTerminal</deliveryStatus>
</sms7:deliveryStatus>
</sms7:notifySmsDeliveryReceipt>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
[sms7:correlator: null]
[address: null]
Process finished with exit code 0
Why are the values null?
There is 3 reason, why ist not working:
The node really doesn't exist!
The node is in a different namespace and you need to use the version of the method that also accepts the namespace: Element#getChild(String, Namespace) or Element#getChildText(String, Namespace).
Most importantly, remember that these methods return only immediate descendents of a node! So if you're looking to get a node nested at the nth level, you will need to walk the tree to its parent and only then can you call #getChild() and actually get the child!
all the examples about parsing xml elements/nodes, that i've found, are about how to extract node attributes/values etc from xml document.
Im interested on how should i extract an entire element from opening tag to closing tag.
Example:
from xml document
<?xml version="1.0"?>
<Employees>
<Employee emplid="1111" type="admin"/>
</Employees>
i would get the complete element
<Employee emplid="1111" type="admin"/>
to saving it in a String variable
Thanks in advance
You can either do the parsing yourself, or use Android's XML parser. This shows how to use the latter.
If you use Android's parser you probably have to parse it completely, and then construct the string <Employee emplid="1111" type="admin"/> by hand.
For now this is the best solution.
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
...
//xml document
String xml = "<?xml version=\"1.0\"?><Employees><Employee emplid=\"1111\" type=\"admin\"/></Employees>";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder parser = factory.newDocumentBuilder();
Document document = parser.parse(new ByteArrayInputStream(xml.getBytes()));
//getting the target element
NodeList list=document.getElementsByTagName("Employee");
Node node=list.item(0);
//writing the element in the string variable
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
StringWriter buffer = new StringWriter();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(new DOMSource(node), new StreamResult(buffer));
String str = buffer.toString();
System.out.println(str);
...
Inspired by this thread
for eg. root=
<root>
<param value="abc">
<param value="bc">
</root>
NodeToInsert could be
<insert><parameterDesc>afds</parameterDesc></insert>
The output should be:
<root>
<insert><parameterDesc>afds</parameterDesc></insert>
<param value="abc">
<param value="bc">
</root>
I'll be really irritated if it turns out I just did your homework for you.
package com.akonizo.examples;
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
public class XmlInsertExample {
/**
* #param args
*/
public static void main(String[] args) {
String initial = "<root><param value=\"abc\"/><param value=\"bc\"/></root>";
try {
// Parse the initial document
ByteArrayInputStream is = new ByteArrayInputStream(initial.getBytes());
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(is);
// Create the new xml fragment
Text a = doc.createTextNode("afds");
Node p = doc.createElement("parameterDesc");
p.appendChild(a);
Node i = doc.createElement("insert");
i.appendChild(p);
Element r = doc.getDocumentElement();
r.insertBefore(i, r.getFirstChild());
r.normalize();
// Format the xml for output
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
// initialize StreamResult with File object to save to file
StreamResult result = new StreamResult(new StringWriter());
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
System.out.println(result.getWriter().toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
The result will be:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<root>
<insert>
<parameterDesc>afds</parameterDesc>
</insert>
<param value="abc"/>
<param value="bc"/>
</root>