How to parse this XML in Android? - java

I am quite new to XML parsing and I have my method of parsing XML. Only that method is for simple XML layouts with just 1 child node.
I now have to parse an XML file with childs that have childs that have childs (got it :)?)
This is the parse-method I have now:
protected Map<String, Maatschappij> getAutopechTel() {
Map<String, Maatschappij> telVoorAutopech = new HashMap<String, Maatschappij>();
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document doc = builder.parse(getAssets().open("autopech.xml"));
NodeList nl = doc.getElementsByTagName("dienst");
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
Maatschappij maat = new Maatschappij();
maat.setNaam(Xml.innerHtml(Xml.getChildByTagName(node, "naam")));
maat.setTel(Xml.innerHtml(Xml.getChildByTagName(node, "tel")));
telVoorAutopech.put(maat.getTel(), maat);
}
} catch (Exception e) {
}
return telVoorAutopech;
}
How must I adjust this in order to parse this type of XML file:
<Message>
<Service>Serviceeee</Service>
<Owner>Bla</Owner>
<LocationFeedTo>Too</LocationFeedTo>
<Location>http://maps.google.com/?q=52.390001,4.890145</Location>
<Child1>
<Child1_1>
<Child1_1_1>ANWB</Child1_1_1>
</Child1_1>
</Child1>
<Message>

You can use SAXParser to parse XML in Android :
Here is a detailed tutorial with example and also another one here by IBM developerWorks.
DOM Parser is slow and consume a lot
memory if it load a XML document
which contains a lot of data. Please
consider SAX parser as solution for
it, SAX is faster than DOM and use
less memory.
Try this one out but I haven't tested this code yet. It recursively traverses all the nodes and adds which are ELEMENT_NODE to the Vector<Node>.
public void traverseNodes(Node node, Vector<Node> nodeList)
{
if(node.getNodeType() == Node.ELEMENT_NODE)
{
nodeList.add(node);
if(node.getChildNodes().getLength() >= 1)
{
NodeList childNodeList = node.getChildNodes();
for(int nodeIndex = 1;nodeIndex < childNodeList.getLength(); nodeIndex++)
{
traverseNodes(childNodeList.item(nodeIndex),nodeList);
}
}
}
}

Related

How do I get relevant information from a JSON output?

I am trying to parse an XML file into JSON. While I am able to parse successfully using a HashMap, the XML file I am using has a lot of irrelevant information which also gets reflected in the JSON.
My XML file is a topology file, basically topology for network elements and their respective processes. So, it is divided into parent and child nodes. Most of the relevant information I seek lie with the parent nodes and I want to disregard the child nodes by whatever means, so that only the parent nodes are available in the JSON.
Here's the code I wrote to parse. I have tried to write code to get child enter code herenodes but I can't figure out how to remove them(like what conditions I can use):
static String nodeType1,nodeType;
static String nodeName1,nodeName;
static String nodeIP1,nodeIP;
public static void main(String[] args) {
try { File fXmlFile = new File("SystemTopology.txt");
DocumentBuilderFactory dbFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("SNOSNE") ;
Map<String, Object> data = new HashMap<String, Object>();
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
Element el = (Element) nNode;
nodeType = el.getAttribute("snostype");
nodeName = el.getAttribute("cimname");
nodeIP = el.getAttribute("snoshostip");
NodeList list = el.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
Node nNode1 = list.item(i);
if(list.item(i).getNodeType() == Node.ELEMENT_NODE){
Element element = (Element) list.item(i);
nodeType1 = element.getAttribute("snostype");
nodeName1 = element.getAttribute("cimname");
nodeIP1 = element.getAttribute("snoshostip");
if(!nodeIP1.isEmpty()) {
System.out.println(nodeType1);
System.out.println(nodeName1);
System.out.println(nodeIP1);
}
}
}
//Need to add conditions here that would get only child nodes
if(!nodeIP.isEmpty()) {
data.put(nodeName, nodeType+","+nodeIP);
}
}
JSONObject json = new JSONObject(data);
System.out.printf( "JSON: %s", json.toString(2));
}
catch (Exception excp)
{
System.out.println("topology file not found " + excp.getMessage());
}
Topology file looks like:
<SNOSNE cimname="EDA_01" snoshostip="1.1.1.1" snostype="EDA">
<SNOSNE cimname="Resources" snoshostip="1.1.1.1" snostype="EDA">
</SNOSNE>
<SNOSNE cimname="CPU" snoshostip="1.1.1.1" snostype="EDA">
</SNOSNE>
...
...
...
</SNOSNE>
Expected output needs to contain only the parent with cimname="EDA_01". And all child nodes need to be disregarded in JSON output.

How to get data from XML node?

I am struggling to get the data out of the following XML node. I use DocumentBuilder to parse XML and I usually get the value of a node by defining the node but in this case I am not sure how the node would be.
<Session.openRs status="success" sessionID="19217B84:AA3649FE:B211FF37:E61A78F1:7A35D91D:48E90C41" roleBasedSecurity="1" entityID="1" />
This is how I am getting the values for other tags by the tag name.
public List<NYProgramTO> getNYPPAData() throws Exception {
this.getConfiguration();
List<NYProgramTO> to = dao.getLatestNYData();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document document = null;
// Returns chunkSize
/*List<NYProgramTO> myList = getNextChunk(to);
ExecutorService executor = Executors.newFixedThreadPool(myList.size());
myList.stream().parallel()
.forEach((NYProgramTO nyTo) ->
{
executor.execute(new NYExecutorThread(nyTo, migrationConfig , appContext, dao));
});
executor.shutdown();
executor.awaitTermination(300, TimeUnit.SECONDS);
System.gc();*/
try {
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource source = new InputSource();
for(NYProgramTO nyProgram: to) {
String reqXML = nyProgram.getRequestXML();
String response = RatingRequestProcessor.postRequestToDC(reqXML, URL);
// dao.storeData(nyProgram);
System.out.println(response);
if(response != null) {
source.setCharacterStream(new StringReader(response));
document = builder.parse(source);
NodeList list = document.getElementsByTagName(NYPG3Constants.SERVER);
for(int iterate = 0; iterate < list.getLength(); iterate++){
Node node = list.item(iterate);
if(node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
nyProgram.setResponseXML(response);
nyProgram.setFirstName(element.getElementsByTagName(NYPG3Constants.F_NAME).item(0).getTextContent());
nyProgram.setLastName(element.getElementsByTagName(NYPG3Constants.L_NAME).item(0).getTextContent());
nyProgram.setPolicyNumber(element.getElementsByTagName(NYPG3Constants.P_NUMBER).item(0).getTextContent());
nyProgram.setZipCode(element.getElementsByTagName(NYPG3Constants.Z_CODE).item(0).getTextContent());
nyProgram.setDateOfBirth(element.getElementsByTagName(NYPG3Constants.DOB).item(0).getTextContent());
nyProgram.setAgencyCode(element.getElementsByTagName(NYPG3Constants.AGENCY_CODE).item(0).getTextContent());
nyProgram.setLob(element.getElementsByTagName(NYPG3Constants.LINE_OF_BUSINESS).item(0).getTextContent());
if(element.getElementsByTagName(NYPG3Constants.SUBMISSION_NUMBER).item(0) != null){
nyProgram.setSubmissionNumber(element.getElementsByTagName(NYPG3Constants.SUBMISSION_NUMBER).item(0).getTextContent());
} else {
nyProgram.setSubmissionNumber("null");
}
I need to get the value for sessionId. What I want to know is the node, I am sure it can't be .I am retrieving the values via tag names so what would be the tag name in this case?
Thanks in advance
You should consider using XPath. At least for me, is so much easy to use and, in your case, in order to get sessionID you could try something like this:
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "/Session.openRs/#sessionID";
String sessionID = xPath.evaluate(expression,document);
You can obtain 'document' like this:
Document document = builder.newDocumentBuilder();
Hope this can help!!

Efficiently unmarshaling a part of a large xml file with JAXB and XMLStreamReader

I want to unmarshall part of a large XML file. There exists solution of this already, but I want to improve it for my own implementation.
Please have a look at the following code: (source)
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xml = new StreamSource("input.xml");
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
xsr.nextTag();
while(!xsr.getLocalName().equals("VersionList")&&xsr.getElementText().equals("1.81")) {
xsr.nextTag();
}
I want to unmarshall the input.xml (given below) for the node: versionNumber="1.81"
With the current code, the XMLStreamReader will first check the node versionNumber="1.80" and then it will check all sub nodes of versionNumber and then it will again move to node: versionNumber="1.81", where it will satisfy the exit condition of the while loop.
Since, I want to check node versionNumber only, iterating its subnodes are unnecessary and for large xml file, iterating all sub nodes of version 1.80 will take lone time. I want to check only root nodes (versionNumber) and if the first root node (versionNumber=1.80) is not matched, the XMLStreamReader should directly jump to next root node ((versionNumber=1.81)). But it seems not achievable with xsr.nextTag(). Is there any way, to iterate through the desired root nodes only?
input.xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<fileVersionListWrapper FileName="src.h">
<VersionList versionNumber="1.80">
<Reviewed>
<commentId>v1.80(c5)</commentId>
<author>Robin</author>
<lines>47</lines>
<lines>48</lines>
<lines>49</lines>
</Reviewed>
<Reviewed>
<commentId>v1.80(c6)</commentId>
<author>Sujan</author>
<lines>82</lines>
<lines>83</lines>
<lines>84</lines>
<lines>85</lines>
</Reviewed>
</VersionList>
<VersionList versionNumber="1.81">
<Reviewed>
<commentId>v1.81(c4)</commentId>
<author>Robin</author>
<lines>47</lines>
<lines>48</lines>
<lines>49</lines>
</Reviewed>
<Reviewed>
<commentId>v1.81(c5)</commentId>
<author>Sujan</author>
<lines>82</lines>
<lines>83</lines>
<lines>84</lines>
<lines>85</lines>
</Reviewed>
</VersionList>
</fileVersionListWrapper>
You can get the node from the xml using XPATH
XPath, the XML Path Language, is a query language for selecting nodes from an XML document. In addition, XPath may be used to compute values (e.g., strings, numbers, or Boolean values) from the content of an XML document. What is Xpath.
Your XPath expression will be
/fileVersionListWrapper/VersionList[#versionNumber='1.81']
meaning you want to only return VersionList where the attribute is 1.81
JAVA Code
I have made an assumption that you have the xml as string so you will need the following idea
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource inputSource = new InputSource(new StringReader(xml));
Document document = builder.parse(inputSource);
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("/fileVersionListWrapper/VersionList[#versionNumber='1.81']");
NodeList nl = (NodeList) expr.evaluate(document, XPathConstants.NODESET);
Now it will be simply loop through each node
for (int i = 0; i < nl.getLength(); i++)
{
System.out.println(nl.item(i).getNodeName());
}
to get the nodes back to to xml you will have to create a new Document and append the nodes to it.
Document newXmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element root = newXmlDocument.createElement("fileVersionListWrapper");
for (int i = 0; i < nl.getLength(); i++)
{
Node node = nl.item(i);
Node copyNode = newXmlDocument.importNode(node, true);
root.appendChild(copyNode);
}
newXmlDocument.appendChild(root);
once you have the new document you will then run a serializer to get the xml.
DOMImplementationLS domImplementationLS = (DOMImplementationLS) document.getImplementation();
LSSerializer lsSerializer = domImplementationLS.createLSSerializer();
String string = lsSerializer.writeToString(document);
now that you have your String xml , I have made an assumption you already have a Jaxb object which looks similar to this
#XmlRootElement(name = "fileVersionListWrapper")
public class FileVersionListWrapper
{
private ArrayList<VersionList> versionListArrayList = new ArrayList<VersionList>();
public ArrayList<VersionList> getVersionListArrayList()
{
return versionListArrayList;
}
#XmlElement(name = "VersionList")
public void setVersionListArrayList(ArrayList<VersionList> versionListArrayList)
{
this.versionListArrayList = versionListArrayList;
}
}
Which you will simple use the Jaxb unmarshaller to create the objects for you
JAXBContext jaxbContext = JAXBContext.newInstance(FileVersionListWrapper .class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(xmlString);
FileVersionListWrapper fileVersionListWrapper = (FileVersionListWrapper) jaxbUnmarshaller.unmarshal(reader);

Parsing XML into Android Application

I am trying to parse this XML onto my Android Application.
I read quite a few questions on parsing the XML here on stackoverflow, yet I am not sure how to handle a for loop everyone mentioned, in my case.
If someone would be nice enough to give me a working example for this case of XML, I'd be very grateful.
THE EXAMPLE CODE I FOUND ON STACKOVERFLOW
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(*/Insert my URL/*);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getElementsByTagName(*/What to write here in my case?/*);
item = new TextView[nodeList.getLength()];
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
item[i] = new TextView(this);
Element fstElmnt = (Element) node;
NodeList itemList = fstElmnt.getElementsByTagName(*/What to write here in my case?/*);
Element itemElement = (Element) itemList.item(0);
itemList = itemElement.getChildNodes();
item[i].setText("item = "
+ ((Node) itemList.item(0)).getNodeValue());
layout.addView(item[i]);
}
}
catch (Exception e) {
System.out.println("XML Pasing Excpetion = " + e);
}
/** Set the layout view to display */
setContentView(layout);
}
The above code is NOT an example that I am using. It's just what I found on the internet how to parse XML on Android App. But my XML seems more complex than the ussually posted ones here.
use XmlPullParser for parsing XML in your android application. It is very easy to use and pretty fast.
I use XmlPullParser in all my applications.
Follow this tutorial it has nice example on how to use XmlPullParser.
http://www.vogella.com/tutorials/AndroidXML/article.html

XML Searching and Parsing

I have an XML file that I am trying to search using Java. I just need to find an element by its Tag name and then find that Tag's value. So for example:
I have this XML file:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="https://company.com/test/xslt/processing_report.xslt"?>
<Certificate xmlns="urn:us:net:exchangenetwork:Company">
<Value1>Veggie</Value1>
<Value2>Fruits</Value2>
<type1>Apple</type1>
<FindME>Red</FindME>
<Value3>Bread</Value3>
</Certificate>
I want to find the value inside of the FindME Tag. I can't use XPath because different files can have different structures, but they always have a FindME tag. Lastly I am looking for the simplest piece of code, I do not care much about performance. Thank you
Here is the code:
XPathFactory f = XPathFactory.newInstance();
XPathExpression expr = f.newXPath().compile(
"//*[local-name() = 'FindME']/text()");
DocumentBuilderFactory domFactory = DocumentBuilderFactory
.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("src/test.xml"); //your XML file
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
System.out.println(nodes.getLength());
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i).getNodeValue());
}
Explained :
//* - match any element node - no matter where they are
local-name() = 'FindME' - where local name - i.e; not the full path - matches 'FindME'
text() - get the node value.
I think you need to read up on XPath because it can very easily solve this problem. So can using getElementsByTagName in the DOM API.
You can still use XPath. All you need to do is use //FindMe (read here on // usage) expression. This finds a the "FindMe" elements from any where in the xml irrespective of its parent or path from the root.
If you are using namespaces then make sure you are making the parser aware of that
String findMeVal = null;
InputStream is = //...
XmlPullParser parser = //...
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(is, null);
int event;
while (XmlPullParser.END_DOCUMENT != (event = parser.next())) {
if (event == XmlPullParser.START_TAG) {
if ("FindME".equals(parser.getName())) {
findMeVal = parser.nextText();
break;
}
}
}

Categories

Resources