JAXM soap message parsing - java

I am getting the following XML back from a .net service:
<?xml version="1.0" encoding="utf-8"?>
<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>
<validateCredentialsResponse
xmlns="http://www.paragon.com/positionmonitor/PositionMonitor">
<validateCredentialsResult>
<ResultData xsi:type="ValidateCredentialsResultData">
<validated>true</validated>
<alreadyLoggedIn>false</alreadyLoggedIn>
</ResultData>
<Status>
<Condition xmlns="">SUCCESS</Condition>
<ErrorCode xmlns="">BO.00000</ErrorCode>
<ErrorDesc xmlns="">OK</ErrorDesc>
</Status>
</validateCredentialsResult>
</validateCredentialsResponse>
</soap:Body>
</soap:Envelope>
...and I'm trying to parse it using JAXM, however the following always evaluates to null:
SOAPEnvelope env = reply.getSOAPPart().getEnvelope();
Can anyone help me out here?

I got nice results using the following code (needs at least Java 1.5):
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Jaxm {
private static List<Element> elements(NodeList nodes) {
List<Element> result = new ArrayList<Element>(nodes.getLength());
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node instanceof Element)
result.add((Element)node);
}
return result;
}
private static Element named(Element elem, String name) {
if (!elem.getNodeName().equals(name))
throw new IllegalArgumentException("Expected " + name + ", got " + elem.getNodeName());
return elem;
}
#SuppressWarnings("unchecked")
public static void main(String[] args) throws IOException, SOAPException {
String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" \r\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \r\n" +
" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n" +
" <soap:Body>\r\n" +
" <validateCredentialsResponse \r\n" +
" xmlns=\"http://www.paragon.com/positionmonitor/PositionMonitor\">\r\n" +
" <validateCredentialsResult>\r\n" +
" <ResultData xsi:type=\"ValidateCredentialsResultData\">\r\n" +
" <validated>true</validated>\r\n" +
" <alreadyLoggedIn>false</alreadyLoggedIn>\r\n" +
" </ResultData>\r\n" +
" <Status>\r\n" +
" <Condition xmlns=\"\">SUCCESS</Condition>\r\n" +
" <ErrorCode xmlns=\"\">BO.00000</ErrorCode>\r\n" +
" <ErrorDesc xmlns=\"\">OK</ErrorDesc>\r\n" +
" </Status>\r\n" +
" </validateCredentialsResult>\r\n" +
" </validateCredentialsResponse>\r\n" +
" </soap:Body>\r\n" +
"</soap:Envelope>\r\n" +
"";
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage msg = factory.createMessage(new MimeHeaders(), new ByteArrayInputStream(xml.getBytes(Charset.forName("UTF-8"))));
msg.saveChanges();
SOAPBody soapBody = msg.getSOAPBody();
for (Element response : elements(soapBody.getElementsByTagName("validateCredentialsResponse"))) {
for (Element result : elements(response.getElementsByTagName("validateCredentialsResult"))) {
List<Element> children = elements(result.getChildNodes());
Element resultData = named(children.get(0), "ResultData");
List<Element> resultDataChildren = elements(resultData.getChildNodes());
boolean validated = Boolean.getBoolean(named(resultDataChildren.get(0), "validated").getTextContent());
boolean alreadyLoggedIn = Boolean.getBoolean(named(resultDataChildren.get(1), "alreadyLoggedIn").getTextContent());
Element status = named(children.get(1), "Status");
List<Element> statusChildren = elements(status.getChildNodes());
String condition = named(statusChildren.get(0), "Condition").getTextContent();
String errorCode = named(statusChildren.get(1), "ErrorCode").getTextContent();
String errorDesc = named(statusChildren.get(2), "ErrorDesc").getTextContent();
System.out.printf("validated=%s alreadyLoggedIn=%s condition=%s errorCode=%s errorDesc=%s\n", validated, alreadyLoggedIn, condition, errorCode, errorDesc);
}
}
}
}

Related

How to get list of All Node Names from XML document using Java

import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
public class comparexmls {
public static void main(String[] argv) throws Exception {
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xmlRecords));
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(is);
NodeList list = doc.getChildNodes();
//System.out.println(doc.getChildNodes().item(2));
for (int i = 0; i < list.getLength(); i++) {
if (list.item(i) instanceof Element) {
Element root = (Element) list.item(i);
System.out.println(root.getNodeName());
break;
}
}
}
static String xmlRecords =
"<Search.UDB.OUT TraceId=\"1234\">\r\n" +
" <Response>Success</Response>\r\n" +
" <Status>\r\n" +
" <System Name=\"X\">\r\n" +
" <Code>00</Code>\r\n" +
" <Message></Message>\r\n" +
" </System>\r\n" +
" <System Name=\"Y\">\r\n" +
" <Code>00</Code>\r\n" +
" <Message></Message>\r\n" +
" </System>\r\n" +
" <System Name=\"Z\">\r\n" +
" <Code>00</Code>\r\n" +
" <Message></Message>\r\n" +
" </System>\r\n" +
" </Status>\r\n" +
" <NumberFound>1</NumberFound>\r\n" +
" <AccountList>\r\n" +
" <Account>\r\n" +
" <AccountNumber>XXXXXXXXXXXX</AccountNumber>\r\n" +
" <CorpNo>XX</CorpNo>\r\n" +
" <Name>Chandra</Name>\r\n" +
" <AddressLine1>100 MAIN ST</AddressLine1>\r\n" +
" <AddressLine2>ANYTOWN</AddressLine2>\r\n" +
" <AddressLine3> GA 123456789</AddressLine3>\r\n" +
" <Block />\r\n" +
" <Reclass />\r\n" +
" <EmbossLine4 />\r\n" +
" <Phone>1234567890</Phone>\r\n" +
" </Account>\r\n" +
" </AccountList>\r\n" +
"</Search.UDB.OUT>";
}
I am getting Search.UDB.OUT only.. How to iterate all the parent and childnodes..
Take a look at the XmlSlurper class in http://stefanfrings.de/bfUtilities/bfUtilities.zip. It's a recursive algorithm.
It reads the whole XML into a simple flat HashMap collecting all element names in the format:
Search.UDB.OUT.TraceId
Search.UDB.OUT.Response
Search.UDB.OUT.Status.System.Name
...
Source code of that class:
package de.stefanfrings.parsing;
import de.stefanfrings.container.ConvertingHashMap;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashSet;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class XmlSlurper
{
public static ConvertingHashMap parse(String xmlDocument) throws ParserConfigurationException, SAXException, IOException
{
ConvertingHashMap targetMap=new ConvertingHashMap();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(xmlDocument));
Document doc=builder.parse(is);
Element rootElement=doc.getDocumentElement();
collectData(rootElement,rootElement.getNodeName().toLowerCase(),targetMap);
return targetMap;
}
/** Collect the content of one element */
private static void collectData(Element element, String currentPath, ConvertingHashMap targetMap)
{
if (element==null)
{
return;
}
// Collect all attributes of this ode
NamedNodeMap attributes = element.getAttributes();
if (attributes!=null)
{
for (int i=0; i<attributes.getLength(); i++)
{
Attr attribute = (Attr) attributes.item(i);
String name = attribute.getLocalName();
if (name==null)
{
name = attribute.getNodeName();
}
String value = attribute.getNodeValue();
targetMap.put(currentPath+"."+name.toLowerCase(), value);
}
}
// Collect all child elements recursively
boolean hasChildren=false;
NodeList children=element.getChildNodes();
if (children!=null)
{
int count=0;
for (int i=0; i<children.getLength(); i++)
{
Node node=children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE)
{
hasChildren=true;
Element child = (Element)children.item(i);
String name=child.getLocalName();
if (name==null)
{
name=child.getNodeName();
}
String key=currentPath+"."+name.toLowerCase();
// do we have already a children with same name?
if (targetMap.containsKey(key))
{
// duplicate the first (existing) item
if (count==0)
{
// Make a copy of the first element and all of its sub elements by inserting the number 0
Set<String> keySet = new HashSet<>();
keySet.addAll(targetMap.keySet());
for (String k:keySet)
{
if (k.equals(key) || k.startsWith(key+"."))
{
String existing=targetMap.get(k);
targetMap.put(k.replace(key,key+"0"),existing);
}
}
}
// add new item
collectData(child,key+String.valueOf(++count),targetMap);
}
else
{
collectData(child,key,targetMap);
}
}
}
}
if (!hasChildren)
{
// Get the text content
String text=element.getTextContent();
targetMap.put(currentPath, text);
}
else
{
targetMap.put(currentPath, ""); // no text
}
}
}
You may replace the ConvertingHashMap by a regular HashMap. The difference is that the ConvertingHash has methods like getInteger() and getDate().

How to read XML to a list of POJOs in Java?

I'm new to XML and im trying to read in an XML page and store its contents in an arraylist.
So far i seem to have been able to get the arraylist filled with the first content, as when i tried an isEmpty, it returned false. so there is definitely containing something.
However, when i try to call the overided tostring method, or even try to call any individual category for that matter, it just returns empty?
can anyone help?
heres the code im working with:
package test;
import java.io.File;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
public class xmlmx {
public static void main(String[] args) {
ArrayList<Anime> list = new ArrayList<Anime>();
try {
File inputFile = new File("c:\\code\\ad\\XMLDB.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(inputFile);
doc.getDocumentElement().normalize();
System.out.println("Root element: " + doc.getDocumentElement().getNodeName());
NodeList nList = doc.getElementsByTagName("Anime");
System.out.println("----------------------------");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
System.out.println("\nCurrent Element :" + nNode.getNodeName());
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
list.add(new Anime(eElement.getAttribute("ID"),
eElement.getAttribute("name"),
eElement.getAttribute("altname"),
eElement.getAttribute("seasons"),
eElement.getAttribute("episodes"),
eElement.getAttribute("status"),
eElement.getAttribute("DS"),
eElement.getAttribute("have"),
eElement.getAttribute("left"),
eElement.getAttribute("plot"),
eElement.getAttribute("connect"),
eElement.getAttribute("image")));
System.out.println(list.get(0).toString());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
the arraylist is of type anime, a class here:
package test;
class Anime{
private String ID;
private String name;
private String altname;
private String seasons;
private String episodes;
private String status;
private String DS;
private String have;
private String left;
private String plot;
private String connect;
private String image;
public Anime(String ID,
String name,
String altname,
String seasons,
String episodes,
String status,
String DS,
String have,
String left,
String plot,
String connect,
String image) {
this.ID = ID;
this.name = name;
this.altname = altname;
this.seasons = seasons;
this.episodes = episodes;
this.status = status;
this.DS = DS;
this.have = have;
this.left = left;
this.plot = plot;
this.connect = connect;
this.image = image;
}
/*
getters and setters here...
*/
#Override
public String toString() {
return "Anime [ID=" + ID +
", name=" + name +
", altname=" + altname +
", seasons=" + seasons +
", episodes=" + episodes +
", status=" + status +
", DS=" + DS +
", have=" + have +
", left=" + left +
", plot=" + plot +
", connect=" + connect +
", image=" + image + "]";
}
}
finally, heres the xml:
<?xml version="1.0" encoding="UTF-8"?>
<Anime>
<record ID="BL1">
<name>Bleach</name>
<altname>Burichi</altname>
<seasons>16</seasons>
<episodes>366</episodes>
<status>Finished</status>
<sound>Dubbed</sound>
<have>All</have>
<left>-/-</left>
<plot>Ichigo gets grim reaper powers, fights reapers, hollows and everything in between</plot>
<connect>Bleach movies</connect>
<image>images/bleach.jpg</image>
</record>
</Anime>
any help would be greatly appreciated, thank you
Hi basically your understanding about the w3c dom xml element is wrong. "name:, "altname" etc are not attributes of "Animie" element. those are "child nodes" of "record" node. So first you have to fetch "record" node by iterating child nodes of "Animie" element. Then you can iterate through the child nodes of "record" element so that you can populate your Anime object.
Here's a simple implementation of your "xmlmx class that works. I had to use a map because you have ommitted the setter methods, this can be improved just trying to fix the xml concepts in your head.
Just replace your class with this.
package test;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import com.sun.org.apache.xerces.internal.dom.DeferredElementImpl;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
public class xmlmx {
public static void main(String[] args) {
ArrayList<Anime> list = new ArrayList<Anime>();
try {
File inputFile = new File("test.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(inputFile);
doc.getDocumentElement().normalize();
System.out.println("Root element: " + doc.getDocumentElement().getNodeName());
Node recordNode = null;
NodeList childNodes = doc.getFirstChild().getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
if (childNodes.item(i).getNodeName().equals("record")) {
recordNode = childNodes.item(i);
break;
}
}
System.out.println("----------------------------");
Map<String, String> map = new HashMap<>();
if (recordNode != null) {
NodeList subNodes = recordNode.getChildNodes();
for (int i = 0; i < subNodes.getLength(); i++) {
if (subNodes.item(i).getNodeType() == Node.ELEMENT_NODE) {
map.put(subNodes.item(i).getNodeName(), subNodes.item(i).getTextContent());
}
}
}
String id = ((DeferredElementImpl) recordNode).getAttribute("ID");
list.add(new Anime(id,
map.get("name"),
map.get("altname"),
map.get("seasons"),
map.get("episodes"),
map.get("status"),
map.get("DS"),
map.get("have"),
map.get("left"),
map.get("plot"),
map.get("connect"),
map.get("image")));
System.out.println(list.get(0));
} catch (Exception e) {
e.printStackTrace();
}
}
}
Use an ObjectMapper like Jackson FasterXML!
new XmlMapper().readValue(yourDataAsInputStream, Anime.class);
or for a list
new XmlMapper().readValue(yourDataAsInputStream, new TypeReference<List<Anime>>(){});
Full Example:
package stack47711679;
import java.util.List;
import org.junit.Test;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
public class HowToReadXmlToAPojoIn2017 {
#Test
public void readXmlToPojo() throws Exception {
ObjectMapper mapper = new XmlMapper();
Anime pojo = mapper.readValue(Thread.currentThread().getContextClassLoader().getResourceAsStream("47711679.xml"), Anime.class);
System.out.println(pojo+"");
}
#Test
public void readXmlToListOfPojo() throws Exception {
ObjectMapper mapper = new XmlMapper();
List<Anime> pojos = mapper.readValue(Thread.currentThread().getContextClassLoader().getResourceAsStream("47711679_v2.xml"), new TypeReference<List<Anime>>(){});
System.out.println(pojos+"");
}
}
Your POJO Anime.java
package stack47711679;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
public class Anime{
#JacksonXmlProperty(isAttribute = true)
public String id;
public String name;
public String altname;
public String seasons;
public String episodes;
public String status;
public String DS;
public String have;
public String left;
public String plot;
public String connect;
public String image;
public String sound;
public Anime(){
}
#Override
public String toString() {
return "Anime [ID=" + id +
", name=" + name +
", altname=" + altname +
", seasons=" + seasons +
", episodes=" + episodes +
", status=" + status +
", DS=" + DS +
", have=" + have +
", left=" + left +
", plot=" + plot +
", connect=" + connect +
", sound=" + sound +
", image=" + image + "]";
}
}
With Testdata:
47711679.xml
<?xml version="1.0" encoding="UTF-8"?>
<Anime id="1">
<name>Bleach</name>
<altname>Burichi</altname>
<seasons>16</seasons>
<episodes>366</episodes>
<status>Finished</status>
<sound>Dubbed</sound>
<have>All</have>
<left>-/-</left>
<plot>Ichigo gets grim reaper powers, fights reapers, hollows and everything in between</plot>
<connect>Bleach movies</connect>
<image>images/bleach.jpg</image>
</Anime>
47711679_v2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Animes>
<Anime id="1">
<name>Bleach</name>
<altname>Burichi</altname>
<seasons>16</seasons>
<episodes>366</episodes>
<status>Finished</status>
<sound>Dubbed</sound>
<have>All</have>
<left>-/-</left>
<plot>Ichigo gets grim reaper powers, fights reapers, hollows and everything in between</plot>
<connect>Bleach movies</connect>
<image>images/bleach.jpg</image>
</Anime>
<Anime id="2">
<name>Something</name>
<altname>else</altname>
<seasons>21</seasons>
<episodes>34</episodes>
<status>to be continued</status>
<sound>Dubbed</sound>
<have>All</have>
<left>-/-</left>
<plot>Yes it has one</plot>
<connect>Bleach movies</connect>
<image>images/bleach.jpg</image>
</Anime>
</Animes>
Prints:
For the list in 47711679_v2.xml:
[Anime [ID=1, name=Bleach, altname=Burichi, seasons=16, episodes=366, status=Finished, DS=null, have=All, left=-/-, plot=Ichigo gets grim reaper powers, fights reapers, hollows and everything in between, connect=Bleach movies, sound=Dubbed, image=images/bleach.jpg], Anime [ID=2, name=Something, altname=else, seasons=21, episodes=34, status=to be continued, DS=null, have=All, left=-/-, plot=Yes it has one, connect=Bleach movies, sound=Dubbed, image=images/bleach.jpg]]
And for the single entry 47711679.xml:
Anime [ID=1, name=Bleach, altname=Burichi, seasons=16, episodes=366, status=Finished, DS=null, have=All, left=-/-, plot=Ichigo gets grim reaper powers, fights reapers, hollows and everything in between, connect=Bleach movies, sound=Dubbed, image=images/bleach.jpg]
I used jackson 2.8.6.
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.8.6</version>
</dependency>

splitting Sitemap into more sitemaps if it has more than maxnumber of urls

I would like to split my Sitemap into Sitemaps, if it has more than maxURLs. The following example should split the Sitemap, if it has more than one url.
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.CharacterData;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class SiteMapSplitter {
public static void main(String[] args){
String sitemapStr = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n" +
"<url>\n" +
"<loc>test1.html</loc>\n" +
"<lastmod>today</lastmod>\n" +
"<changefreq>daily</changefreq>\n" +
"<priority>1.0</priority>\n" +
"</url>\n" +
"<url>\n" +
"<loc>test2.html</loc>\n" +
"<lastmod>yesterday</lastmod>\n" +
"<changefreq>daily</changefreq>\n" +
"<priority>1.0</priority>\n" +
"</url></urlset>";
try {
splitSitemap(sitemapStr);
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
static private void splitSitemap(String sitemapStr) throws ParserConfigurationException {
DocumentBuilder db = null;
try {
db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(sitemapStr));
Document doc = null;
try {
doc = db.parse(is);
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
NodeList nodes = doc.getElementsByTagName("url");
int maxURLs = 1;
Set<String> smURLsSet= new HashSet<String>();
if (nodes.getLength()>maxURLs){
for (int i = 0; i < nodes.getLength(); i++) {
StringBuilder smURLsBuilder = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n");
for (int k = 0; k<maxURLs; k++){
Element element = (Element) nodes.item(i);
smURLsBuilder.append(element);
}
smURLsSet.add(smURLsBuilder.toString());
}
Iterator i = smURLsSet.iterator();
while(i.hasNext()){
System.out.println(i.next());
}
}
}
}
The problem is that Element element = (Element) nodes.item(i); smURLsBuilder.append(element);
does not append the whole element (in this case the url and its childreen) to the smURLsBuilder. How to do this?
You should consider using an object oriented approach to the sitemap. Either with data binding (JAXB) or even shorter using data projection (Disclosure: I'm affiliated with that project). This way you do not need to create the XML by string concatenation.
public class SitemapSplitter {
static String sitemapStr = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n" +
"<url>\n" +
"<loc>test1.html</loc>\n" +
"<lastmod>today</lastmod>\n" +
"<changefreq>daily</changefreq>\n" +
"<priority>1.0</priority>\n" +
"</url>\n" +
"<url>\n" +
"<loc>test2.html</loc>\n" +
"<lastmod>yesterday</lastmod>\n" +
"<changefreq>daily</changefreq>\n" +
"<priority>1.0</priority>\n" +
"</url></urlset>";
public interface Sitemap {
#XBWrite("/urlset/url")
Sitemap setUrls(List<? extends Node> urls);
}
public static void main(String... args) {
XBProjector projector = new XBProjector(Flags.TO_STRING_RENDERS_XML);
// Get all urls from existing sitemap.
List<Node> urlNodes = projector.onXMLString(sitemapStr).evalXPath("/xbdefaultns:urlset/xbdefaultns:url").asListOf(Node.class);
for (Node urlNode: urlNodes) {
// Create a new sitemap, here with only one url
Sitemap newSitemap = projector.onXMLString(sitemapStr).createProjection(Sitemap.class).setUrls(Collections.singletonList(urlNode));
System.out.println(newSitemap);
}
}
}
This program prints out
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>test1.html</loc>
<lastmod>today</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
</urlset>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>test2.html</loc>
<lastmod>yesterday</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
</urlset>

Keep getting null pointer exception

here is my program: basically i have an xml file and from that file i have to decode a base64 string but i keep getting NullPointerException..please help! code is as follows...
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.commons.codec.binary.Base64;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Arrays;
public class main {
public static void main(String[] args) throws Exception {
SAXParserFactory parserFactor = SAXParserFactory.newInstance();
SAXParser parser = parserFactor.newSAXParser();
SAXHandler handler = new SAXHandler();
//parser.parse(ClassLoader.getSystemResourceAsStream("ATMSPopulateDMSData.xml"),
// handler);
parser.parse(new FileInputStream("C:\\Users\\qta6754\\workspace\\Java_Dev\\XML64_Decoded\\ATMSMessageData.xml"), handler);
for (NeededInfo emp : handler.empList) {
System.out.println(emp);
}
}
}
class SAXHandler extends DefaultHandler {
List<NeededInfo> empList = new ArrayList<>();
NeededInfo emp = null;
String content = null;
String did = null;
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
switch (qName) {
case "dMSDeviceStatus":
emp = new NeededInfo();
emp.id = attributes.getValue("id");
emp.Read();
break;
}
}
public void characters(char[] ch, int start, int length) throws SAXException {
content = String.copyValueOf(ch, start, length).trim();
}
}
class NeededInfo {
String id;
String firstName;
String lastName;
String location;
String organization_id;
String operator_id;
String device_id;
String dms_device_status;
String dms_current_message;
String last_comm_time;
String date;
String time;
public String toString() {
//return firstName + " " + lastName + "(" + id + ")" + location+date+time+device_name;
return "Organization id: " + organization_id + "\n" + "Operator id: " + operator_id + "\n" + "Device id: " + device_id + "\n"
+ "Dms Device Status: " + dms_device_status + "\n" + "Dms Current Message: " + dms_current_message + "\n" + "Last Comm Time" + "\n"
+ "Time: " + time + "\n" + "Date: " + date + "\n" + "decoded string is: " + "\n" + "-------------------------------------";
}
public void Read() {
byte[] byteArray = Base64.decodeBase64(dms_current_message.getBytes());
String decodedString = new String(byteArray);
System.out.print("The decoded message is: " + decodedString);
// return decodedString;
}
}
It's hard to guess where you're getting your error, but I'm assuming here:
byte[] byteArray = Base64.decodeBase64(dms_current_message.getBytes());
I don't see dms_current_message being initialized ever, yet you're calling a method on it, which would definitely result in the null pointer exception.
Your Read method accesses the dms_current_message which is never initialized in all the code you included in your question.
byte[] byteArray = Base64.decodeBase64(dms_current_message.getBytes());

How to change values of inner node of a xml using jdom in java

I have tried changing xml values with the help of jdom by referring this link
- http://www.mkyong.com/java/how-to-modify-xml-file-in-java-jdom/
xml shown in the sample:
<?xml version="1.0" encoding="UTF-8"?>
<company>
<staff id="1">
<firstname>yong</firstname>
<lastname>mook kim</lastname>
<nickname>mkyong</nickname>
<salary>5000</salary>
</staff>
</company>
The thing i am not clear that how to handle the following xml scenario:
<?xml version="1.0" encoding="UTF-8"?>
<company>
<staff>
<firstname>yong</firstname>
<lastname>mook kim</lastname>
<nickname>mkyong</nickname>
<salary>
<basic>1000</basic>
<hra>150</hra>
</salary>
</staff>
<staff>
<firstname>sanjay</firstname>
<lastname>machani</lastname>
<nickname>chong</nickname>
<salary>
<basic>2000</basic>
<hra>200</hra>
</salary>
</staff>
</company>
My staff tag won't be having id and also i would be having child tags for salary.
But i need to change salary for sanjay(firstname) in xml using java.
Any suggestions would be helpful.
If you are using JDOM you can iterate through the elements with this:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
public class yourClass{
public static void main(String[] args) {
File xml = new File("yourFile.xml");
try {
Document doc = (Document) new SAXBuilder().build(xml);
Element rootNode = doc.getRootElement();
List list = rootNode.getChildren("staff");
XMLOutputter xmlOut = new XMLOutputter();
for (int i = 0; i < list.size(); i++) {
Element node = (Element) list.get(i);
if (node.getChildText("firstname").equals("sanjay"))
node.getChild("salary").getChild("basic").setText("250000");
xmlOut.setFormat(Format.getPrettyFormat());
xmlOut.output(doc, new FileWriter("yourFile.xml"));
}
} catch (IOException io) {
System.out.println(io.getMessage());
} catch (JDOMException jdomex) {
System.out.println(jdomex.getMessage());
}
}
}
How about using XPath:
public class ReadSalaryFromStaffTest {
private String xmlData;
#Before
public void init() {
xmlData = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<company>\n" +
" <staff>\n" +
" <firstname>yong</firstname>\n" +
" <lastname>mook kim</lastname>\n" +
" <nickname>mkyong</nickname>\n" +
" <salary>\n" +
" <basic>1000</basic>\n" +
" <hra>150</hra>\n" +
" </salary>\n" +
" </staff>\n" +
" <staff>\n" +
" <firstname>sanjay</firstname>\n" +
" <lastname>machani</lastname>\n" +
" <nickname>chong</nickname>\n" +
" <salary>\n" +
" <basic>2000</basic>\n" +
" <hra>200</hra>\n" +
" </salary>\n" +
" </staff>\n" +
"</company>";
}
#Test
public void shouldChangeBaseSalaryInLastNameMachani() throws Exception{
final SAXBuilder saxbuilder = new SAXBuilder();
final Document document = saxbuilder.build(new StringReader(xmlData));
final XPathExpression<Element> compile = XPathFactory.instance().compile("//lastname[text()=\"machani\"]/../salary/basic", new ElementFilter());
final Element machaniBaseSalary = compile.evaluateFirst(document);
assertThat(machaniBaseSalary.getText(), is("2000"));
machaniBaseSalary.setText("2100");
assertThat(machaniBaseSalary.getText(), is("2100"));
}
}

Categories

Resources