0

I tried understanding all other answers in stackoverflow.But I am not able to relate those answers to my question.

When I call a web service, I get response. I get schema by response.getData();(The XML of the data table containing the results.) (return type String). We don't know what data we get in that XML.

I need to use a 3rd party parser, so that when I give the above string to one method in that parser it should return all the elements in that XML and then I can print the required elements.

I don't want to start parsing the XML myself. Is there a way I can do this? (Does it even make any sense?). Sorry If I am totally wrong. (using Axis2/eclipse) (Edited)

Edit: Adding the code I've tried already.

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
NodeList nodeList = null;


        try {
            String xml = res2.getResult().getRawData();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document document = db.parse(new ByteArrayInputStream(xml.getBytes()));
            nodeList = document.getElementsByTagName("PhoneNumber");
            NamedNodeMap attrib = document.getAttributes();
            for (int i = 0; i < attrib.getLength(); i++) {
                String nodeName = attrib.item(i).getNodeName();
                //nodeName
                String nodeValue = attrib.item(i).getNodeValue();
            }

But I am not sure if the PhoneNumber is with that tag or other name. Also we don't know how many tags we have.

Thanks, Using the code by SyamS, I am able to print all the nodes and corresponding values from xml. Now I want to store that into a hashmap with key as node name and node values in a list.

Example XML :

<Docs>
<Doc>
<Id>12</Id>
<Phone>1234</Phone>
</Doc>
<Doc>
<Id>147</Id>
<Phone>12345</Phone>
<Locked>false</Locked>
<BID>2</BID>
<DocId>8</DocId>
<Date>2014-02-04T12:18:50.063-07:00</Date>
<Urgent>false</Urgent>
</Doc>
</Docs>
Jenny
  • 345
  • 3
  • 5
  • 15
  • Why do you want to parse an XML Schema ? I assume that you want to handle a response in XML and the "required elements" are elements in this XML data file? (An XML Schema *defines* the structure for XML data files.) – laune Jan 22 '15 at 16:36
  • Hello, please see the edits in my question. Forget about schema. I get XML of DataTable. Now I need to get the data from that xml(like userName, id, ssn, email and we don't know what other data we get in that xml). Now I want it parsed, so that I can get all the results they are sending and use the required results. – Jenny Jan 22 '15 at 16:58
  • @Jenny I'm thinking about the class that can be written to handle this. What is the object your XML is stored in? I would like to know how you will pass the XML into a method parameter or class constructor. – ThisClark Jan 22 '15 at 17:23
  • I will store the incoming data(as string) into a file.xml. So that I can give this xml file to a parser that parses and prints all the attributes and their values. (I am assuming this is how it works.) – Jenny Jan 22 '15 at 17:28

2 Answers2

1

You need not go for a third party library for this. you could simply identify all leaf nodes using xpath and read the value (as well as attributes). For example

public static Map<String, List<String>> parseXml(String xml) throws XMLStreamException {
    StringBuilder content = null;
    Map<String, List<String>> dataMap = new HashMap<>();
    XMLInputFactory factory = XMLInputFactory.newInstance();
    InputStream stream = new ByteArrayInputStream(xml.getBytes());
    XMLStreamReader reader = factory.createXMLStreamReader(stream);

    while (reader.hasNext()) {
        int event = reader.next();

        switch (event) {
            case XMLStreamConstants.START_ELEMENT:
                content = new StringBuilder();
                break;

            case XMLStreamConstants.CHARACTERS:
                if (content != null) {
                    content.append(reader.getText().trim());
                }
                break;

            case XMLStreamConstants.END_ELEMENT:
                if (content != null) {
                    String leafText = content.toString();
                    if(dataMap.get(reader.getLocalName()) == null){
                        List<String> values = new ArrayList<>();
                        values.add(leafText);
                        dataMap.put(reader.getLocalName(), values);
                    } else {
                        dataMap.get(reader.getLocalName()).add(leafText);
                    }
                }
                content = null;
                break;

            case XMLStreamConstants.START_DOCUMENT:
                break;
        }

    }

    return dataMap;
}
Syam S
  • 8,421
  • 1
  • 26
  • 36
  • Thanks. but Does XPath also loads the file into memory? We will be receiving large XML files and we don't want it to load into memory. The code I wrote got rejected for the same reason as I used DOM. – Jenny Jan 22 '15 at 19:22
  • Yes. Its a DOM model. If you have to deal with large xml you may want to look at SAX parser or StAX parser. Updating my answer with a StAx parser solution. – Syam S Jan 23 '15 at 10:03
  • Awesome! Now I got a different problem. If my xml has 3 nodes like name, email and phone, then I can save those into a pojo class. But now the situation is we dont know what all data we have in the incoming xml. How can I store that? – Jenny Jan 28 '15 at 19:37
  • I don't fully understand that question. You can get the node name. So you could write a switch statement to set email filed of pojo if the node name is "email" ans so on.. If you could provide a sample xml I could try and create the pojo. – Syam S Jan 29 '15 at 11:14
  • Sure. Will send you one ASAP. Thanks – Jenny Jan 29 '15 at 16:57
  • Hi, Can you please check my edit in post and give me suggestions? I am trying to store nodename as key and values as list in a hashmap and return hashmap instead of printing the values. Thanks – Jenny Feb 03 '15 at 16:08
  • Updated my answer. The stax parser will return a map with data and list of values. – Syam S Feb 03 '15 at 17:58
  • This Stax parser is unable to parse the UTF-16 encoding. I am getting com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character '?' (code 15428 / 0x3c44) in prolog; expected '<' at [row,col {unknown-source}]: [1,1]. exception. Can you please help me with this too? – Jenny Feb 06 '15 at 20:08
  • It should be fine.. Can you share the actual xml.. I mean just a snippet of where its failing.. – Syam S Feb 09 '15 at 09:55
0

You should read answers related to Best XML parser for Java. Using the example XML from Sample XML File (books.xml) which I've downloaded to a temp folder on my C: drive, you might use Java's native SAXParser library. Here's an example class you might use to iterate through all the elements in XML. Create the class in your project, and call its parse method as:

File xml = new File("c:/temp/books.xml");
MySaxParser sax = new MySaxParser(xml);
sax.parseXml();

This is the class you can copy into your project to try it out. Modify according to your needs, of course. The imports should direct you to the appropriate Java API pages such as Class SAXParser to begin with.

import java.io.File;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
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;

public class MySaxParser extends DefaultHandler {
    private String absolutePathToXml = "";
    public MySaxParser(File xml) {
        absolutePathToXml = xml.getAbsolutePath();
    }
    /**
     * Parses an XML file into memory
     */
    public void parseXml() {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            SAXParser parser = factory.newSAXParser();
            parser.parse(absolutePathToXml, this);
        } catch (ParserConfigurationException e) {
            System.out.println("ParserConfigurationException: ");
            e.printStackTrace();
        } catch (SAXException e) {
            System.out.println("SAXException: ");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("IOException: ");
            e.printStackTrace();
        }
    }
    /**
     * Event: Parser starts reading an element
     */
    @Override
    public void startElement(String s1, String s2, String elementName, Attributes attributes) 
            throws SAXException {
        //print an element's name
        System.out.println("element: " + elementName);
        //print all attributes for this element
        for(int i = 0; i < attributes.getLength(); i++) {
            System.out.println("attribute: " + attributes.getValue(i));
        }
    }
}
Community
  • 1
  • 1
ThisClark
  • 14,352
  • 10
  • 69
  • 100
  • Thanks. But we don't want to load the file into memory as we will be receiving large files. and in a bulk. Sorry for not mentioning the requirement beforehand. – Jenny Jan 22 '15 at 19:23
  • @Jenny It sounds like you need StAX parser (STreaming Api for Xml processing). Check out http://woodstox.codehaus.org/ – ThisClark Jan 22 '15 at 20:35
  • Now I got a different problem. If my xml has 3 nodes like name, email and phone, then I can save those into a pojo class. But now the situation is we dont know what all data we have in the incoming xml. How can I store that? – Jenny Jan 28 '15 at 20:54