VictorCreator
VictorCreator

Reputation: 744

Iterate through all XML tags with indenting using java

So, I have the following XML file sample:

<Entry>
      <ns0:entity-Person>
        <ns0:Cell>333-333-3333</ns0:CellPhone>
        <ns0:DOB>1970-01-01T01:00:00-05:00</ns0:DateOfBirth>
        <ns0:FN>Raymond</ns0:FirstName>
        <ns0:Gender>M</ns0:Gender>
      </ns0:entity-Person>
      <ns0:EmailAddress1>[email protected]</ns0:EmailAddress1>
      <ns0:EmailAddress2>[email protected]</ns0:EmailAddress2>
        <ns0:Entry>
          <ns1:OfficialIDType>SSN</ns1:OfficialIDType>
          <ns1:OfficialIDValue>342-56-8729</ns1:OfficialIDValue>
        </ns0:Entry>

.. ..

and I want the following output:

Entry
    ns0:entity-Person
        ns0:CellPhone
        ns0:DateOfBirth
        ns0:FN
        ns0:Gender
    ns0:EmailAddress1
    ns0:EmailAddress2
    ns0:Entry
        ns1:OfficialIDType
        ns1:OfficialIDValue

So, Basically, I want to have an indent ("\t" in java) for the child nodes of every parent node.

as for now, I have the following code (with recursion):

public static void main(String[] args) throws SAXException, IOException,
        ParserConfigurationException, TransformerException {

    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
    Document document = docBuilder.parse(new File("C:\\sub.xml"));

    parseTheTags(document.getDocumentElement());
}

public static void parseTheTags(Node node) {
    System.out.println(node.getNodeName());

    NodeList nodeList = node.getChildNodes();
    for (int i = 0; i < nodeList.getLength(); i++) {
        Node currentNode = nodeList.item(i);
        if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
            parseTheTags(currentNode);    
        }
    }
}

I also know how to do this without recursion, but it's the indenting that I'm unable to do. I know its going to be some small change in the code somewhere, but I've already spent quite some time on this, to no avail.

That's when i thought stackoverflow could, perhaps, help me!

EDITED CODE: Now, appending a tab for each child node: Output has issues though

public class NewParseXMLTags {

    public static void main(String[] args) throws SAXException, IOException,
        ParserConfigurationException, TransformerException {

    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();

    Document document = docBuilder.parse(new File("C:\\Users\\parasv1\\Desktop\\Self\\sub.xml"));

    StringBuilder tmp = new StringBuilder();

    tmp.append("");
    parseTheTags(tmp, document.getDocumentElement());

}

public static void parseTheTags(StringBuilder indentLevel, Node node) {

    StringBuilder indent = new StringBuilder();

System.out.println(indentLevel+node.getNodeName());


NodeList nodeList = node.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
    Node currentNode = nodeList.item(i);

    if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
        if (currentNode.hasChildNodes())
        {
            indent.append("\t");
            parseTheTags(indent, currentNode);      
            }       
        }
     }
   }
}

ANSWER FOUND: So, after some good thinking and help from Sbodd, I found the fix: It's pretty simple!

public class ParseXML {

    public static void main(String[] args) throws SAXException, IOException,
        ParserConfigurationException, TransformerException {

    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();

    Document document = docBuilder.parse(new File("C:\\Users\\parasv1\\Desktop\\Self\\sub.xml"));

    String tmp = new String();

    tmp = "";
    parseTags(tmp, document.getDocumentElement());

}

    public static void parseTags (String indentLevel, Node node) {
          //print out node-specific items at indentLevel
        System.out.println(indentLevel+node.getNodeName());
          String childIndent = indentLevel + "\t";


          NodeList nodeList = node.getChildNodes();
          for (int i = 0; i < nodeList.getLength(); i++) {
                Node n = nodeList.item(i);
                if (n.getNodeType() == Node.ELEMENT_NODE) {

            parseTags(childIndent, n);
          }
        }


    }           

Any help with his would be appreciated!

Upvotes: 0

Views: 1262

Answers (2)

Sbodd
Sbodd

Reputation: 11454

The short form is: add an indentLevel parameter to parseTheTags. On each recursive call, increment indentLevel, and use that to format your output.

Edit for updated code: You're not actually using indentLevel recursively; the value you're passing to the child calls, indent, isn't related to the indentLevel variable at all. Additionally, you probably don't want to be using a StringBuilder for your recursive-depth variable - changes to it will propagate up and down your recursive call heirarchy.

Your basic call structure should look roughly like

public void parseTags (String indentLevel, Node node) {
  //print out node-specific items at indentLevel
  String childIndent = indentLevel + "\t";

  for (Node n : /*whatever nodes you're recursing to*/) {
    parseTags(childIndent, n);
  }
}

This is a pretty standard recursion construct. Take an action at your current node, increment the value of your recursive-depth-counter, and make your recursive calls as appropriate.

Upvotes: 1

suhas khot
suhas khot

Reputation: 85

So your final code should look like

public static void main(String[] args) throws SAXException, IOException,
        ParserConfigurationException, TransformerException {

    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
    Document document = docBuilder.parse(new File("C:\\sub.xml"));
    Transformer t = TransformerFactory.newInstance().newTransformer();
    t.setOutputProperty(OutputKeys.INDENT, "yes");
    t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
    ByteArrayOutputStream s = new ByteArrayOutputStream();
    t.transform(new DOMSource(document),new StreamResult(s));
    System.out.println(new String(s.toByteArray()));
}

Upvotes: 0

Related Questions