how should I store xml data in a java class - java

I am just beginning to learn to read xml in java. My question is very basic. How do I store attributes and sub-elements of an xml element in a java class.
Thus if I have a simple xml file as follows :
<?xml version="1.0"?>
<class>
<student rollno="393">
<firstname>dinkar</firstname>
<lastname>kad</lastname>
<nickname>dinkar</nickname>
<marks>85</marks>
</student>
<student rollno="493">
<firstname>Vaneet</firstname>
<lastname>Gupta</lastname>
<nickname>vinni</nickname>
<marks>95</marks>
</student>
<student rollno="593">
<firstname>jasvir</firstname>
<lastname>singn</lastname>
<nickname>jazz</nickname>
<marks>90</marks>
</student>
</class>
How do I design a java class to store student data. If sub-elements are stored as data members then how should I store the attribute rollno

I recommend you to use JAXB to map XML file into POJO objects.

First create a Student bean class as below:
public class Student {
private int id;
private String firstName;
private String lastName;
private String nickName;
private int marks;
// getters and setters
}
Then you can use DOM parser or SAX parser util populate the data.

You should use the TransformerFactory class as shown:
try {
Document document = null;
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
File f = new File(fileName + ".xml");
StreamResult result = new StreamResult(f);
transformer.transform(source, result);
} catch (TransformerException e) {
throw e;
}
Remember that you have to add TransformerException to the method signature.

Related

How to access SOAP message elements?

So i am trying to replace the values of username and password in the XML file containing a SOAP message. Here are the elements:
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken u:Id="uuid-68f84594-d592-470b-9bbc-b29f58b4756f-1">
<o:Username></o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"></o:Password>
</o:UsernameToken>
</o:Security>
Basically, i want to take the username and password values from my config file, and place them in the username and password fields within the XML file containing the soap message. This is my attempt, and it throws a NPE at the docElement.getElementsByTagName lines:
public void updateUserDetails() {
final Properties configProperties = new Properties();
try {
configProperties.load(new FileInputStream(PROPERTIES));
final Document requestDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new FileInputStream(SOAP_REQUEST));
final Element docElement = requestDoc.getDocumentElement();
docElement.getElementsByTagName("Username").item(0).setTextContent(configProperties.getProperty("username"));
docElement.getElementsByTagName("Password").item(0).setTextContent(configProperties.getProperty("password"));
} catch(IOException | ParserConfigurationException | SAXException exception) {
LOGGER.error("There was an error loading the properties file", exception);
}
}
Any help will be appreciated!
It seems to be related to a namespace problem.
Try specifying the namespace for your tag:
String namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
final Document requestDoc = factory.newDocumentBuilder().parse(new FileInputStream(SOAP_REQUEST));
docElement.getElementsByTagNameNS(namespace, "Username").item(0).setTextContent(configProperties.getProperty("username"));
docElement.getElementsByTagNameNS(namespace, "Password").item(0).setTextContent(configProperties.getProperty("password"));
Also, don't forget in the end to write the result back to file:
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource domSource = new DOMSource(requestDoc);
StreamResult streamResult = new StreamResult(new File(SOAP_REQUEST));
transformer.transform(domSource, streamResult);

Fill data in XML from another XML file dynamically (Java)

I have a xml file where I would like to fill in values from another xml file. For example, if I have data.xml:
<Data>
<Person>
<Name>neby</Name>
<Phone>
<Home>5553456789</Home>
<Mobile>5559879876</Mobile>
</Phone>
</Person>
</Data>
I want to fill in test.xml like this (Data taken from the above file):
<Test>
<Name>${Name}</Name>
<Number>${Home}</Number>
</Test>
In my Java program, I create XML files during runtime. I would like to give a file name, "pass" it to test.xml, have test.xml read it, and fill in the text.
Is there a way to do this?
Am I doing it correctly? All I get is the encoding. Never mind, I got it to work. Using the data.xml from above.
MyXSL.xsl:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:for-each select="Data/Person">
<Test>
<Name><xsl:value-of select="Name"/></Name>
<Number><xsl:value-of select="Home"/></Number>
</Test>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Code:
try {
File stylesheet = new File("MyXSL.xsl");
File dataFile = new File("data.xml");
Document document = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().parse(dataFile);
StreamSource stylesource = new StreamSource(stylesheet);
Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource);
StringWriter stringWriter = new StringWriter();
transformer.transform(new DOMSource(document), new StreamResult(stringWriter));
System.out.println(stringWriter.toString());
} catch(Exception e){
e.printStackTrace();
}
Output: <?xml version="1.0" encoding="UTF-8"?>
What am I doing wrong? Above code works.
Create XSLT and then something like that (very simple from oracle java tuts):
// ...
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;
// ...
public class Stylizer {
// ...
public static void main (String argv[]) {
// ...
try {
File stylesheet = new File(argv[0]);
File datafile = new File(argv[1]);
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.parse(datafile);
// ...
StreamSource stylesource = new StreamSource(stylesheet);
Transformer transformer = Factory.newTransformer(stylesource);
}
}
}
All informations and step-by-step guide to create XSLT and this sample app is here.

How to stop XML Tag Attributes from sorting in Ascending Order after modifying the XML file using Java?

I have written a program to find all XML files matching a particular pattern in a directory and modify it by adding a new tag.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<paths>
<upgradepath startversion="1.4.0.0" moduleid="${moduleId}" endversion="1.4.0.1">
<steps>
<!-- Put scripts here to go from 1.4.0.0 to 1.4.0.1 -->
</steps>
</upgradepath>
<upgradepath startversion="1.4.0.1" moduleid="${moduleId}" endversion="1.4.0.2">
<steps>
<!-- Put scripts here to go from 1.4.0.1 to 1.4.0.2 -->
</steps>
</upgradepath>
</paths>
After running my program the XML file gets modified as below :
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<paths>
<upgradepath endversion="1.4.0.1" moduleid="${moduleId}" startversion="1.4.0.0">
<steps>
<!-- Put scripts here to go from 1.4.0.0 to 1.4.0.1 -->
</steps>
</upgradepath>
<upgradepath endversion="1.4.0.2" moduleid="${moduleId}" startversion="1.4.0.1">
<steps>
<!-- Put scripts here to go from 1.4.0.1 to 1.4.0.2 -->
</steps>
</upgradepath>
<upgradepath endversion="1.4.0.3" moduleid="${moduleId}" startversion="1.4.0.2">
<steps>
<!--Put scripts here to go from 1.4.0.2 to 1.4.0.3-->
</steps>
</upgradepath>
</paths>
If you see the attributes of all the tags you will see that they have all been rearranged in ascending order. The startversion attribute now appears last and the endversion attribute appears first. I want the original order of the attributes after modification of the XML file. I have tried almost everything and have lost all hope. Is there any way I can do this? Also is there a way to sort the attributes in descending order? It's not the right solution but it helps.
Here is a code snippet from the program I am using to modify the files :
private static void updateXMLFiles(String sStartVersion, String sEndVersion) {
try {
for (int c = 0; c < pathsList.size(); c++) {
File xmlFile = new File(pathsList.get(c).toString());
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder;
dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile);
doc.getDocumentElement().normalize();
// Get the last <upgradepath> tag in the file.
// Method Call to verify the version entered and update the XML Files.
// Write the updated document to the file.
doc.getDocumentElement().normalize();
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(pathsList.get(c).toString()));
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.transform(source, result);
}
catch (SAXException e1) {
e1.printStackTrace();
}
catch (ParserConfigurationException e1) {
e1.printStackTrace();
}
catch (IOException e1) {
e1.printStackTrace();
}
catch (TransformerException e1) {
e1.printStackTrace();
}
}
private static void addNewVersion(Document doc, String sStartVersion, String sEndVersion) {
Element element = doc.getDocumentElement();
Element upgradePath = doc.createElement("upgradepath");
upgradePath.setAttribute("startversion", sStartVersion);
upgradePath.setAttribute("moduleid", "${moduleId}");
upgradePath.setAttribute("endversion", sEndVersion);
Element steps = doc.createElement("steps");
Comment comment = doc.createComment("Put scripts here to go from " + sStartVersion + " to " + sEndVersion);
steps.appendChild(comment);
upgradePath.appendChild(steps);
element.appendChild(upgradePath);
}
Is there any way I can keep the order of the attributes intact or in the worst case arrange it in descending order?
A friend of mine suggested I try out JAXB but I couldn't find a way to achieve this. If someone thinks JAXB can solve this do mention how to format an existing XML file and not creating one.
Another issue which is not a major concern is that although I have used the
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
the newly added tags are not indented correctly. Any way to fix this?
#XmlType(propOrder = {"startversion", "moduleid", "endversion", "steps"})
public class XmlSubModel {
private String startversion = "";
private String moduleid = "";
private String endversion = "";
private String steps = "";
#XmlAttribute
public String getStartversion() {
return startversion;
}
public void setStartversion(String startversion) {
this.startversion = startversion;
}
#XmlAttribute
public String getModuleid() {
return moduleid;
}
public void setModuleid(String moduleid) {
this.moduleid = moduleid;
}
#XmlAttribute
public String getEndversion() {
return endversion;
}
public void setEndversion(String endversion) {
this.endversion = endversion;
}
public String getSteps() {
return steps;
}
public void setSteps(String steps) {
this.steps = steps;
}
}

Allowed Special Character in Transformer

I am trying to send xml file to server after processing it which has some special character like "佥佬佧佼A£".
Currently code looks like
public class Utils {
public static String transformToString(Document activeDocument) throws TransformerException{
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.INDENT, "true");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
StringWriter writer = new StringWriter();
transformer.transform(new DOMSource(document), new StreamResult(writer));
writer.toString();
}
Test class
public class Test {
public static void main(String[] args){
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlPath);
//Doing some process on doc and changing other values
String xmlString = Utils.transformToString(doc);
// Sending xml to soap
HttpPost post = new HttpPost(endpoint);
post.setEntity(new StringEntity(xmlString));
post.setHeader(new BasicHeader("content-type", "text/xml"));
.................
}
}
XML file
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope ....>
<soapenv:Header/>
<soapenv:Body>
<Test>
<Id>佥佬佧佼A£</Id>
..............
..........
</Test>
.........
I am getting xmlString with Id value : ????A£
What I want is : 佥佬佧佼A£
How can I do that ? I just want String format of that XML.
EDIT : I am loading one XML, Doing some changes into it, and sending that XML to SOAP, by Setting that document to httpPost.setEntity()
Thanks,
Ankit
You can try:
encoding="UTF-16"
instead of
encoding="UTF-8"

XStream(new StaxDriver()) without XML declaration

My program JAVA:
public static String toXml() {
KtpMessage ktpMessage =new KtpMessage();
ktpMessage.setdetails("test");
XStream xstream = new XStream(new StaxDriver());
String objectXml = xstream.toXML(ktpMessage);
return objectXml;
The result is :
<?xml version='1.0' encoding='utf-8'?><myclasses.Message><details>test</details></myclasses.Message>
my problem:
I want to generate the "objectXml" but without <?xml version='1.0' encoding='utf-8'?>
how can I do that ?
i want have this result:
<myclasses.Message><details>test</details></myclasses.Message>
thanks for your help
If you create your own StaxWriter you can use the constructor that tells it not to write the startDocument StAX event (which is what creates the XML declaration). Something like this (exception handling omitted):
StaxDriver drv = new StaxDriver();
XStream xstream = new XStream(drv);
StringWriter strWriter = new StringWriter();
StaxWriter sw = new StaxWriter(drv.getQnameMap(),
drv.getOutputFactory().createXMLStreamWriter(strWriter),
false, // don't do startDocument
true); // do repair namespaces
xstream.marshal(ktpMessage, sw);
sw.close();
String objectXml = strWriter.toString();

Categories