0

I was looking thru StackOverflow but i can't find best answer. I need to read XML file in JAVA. My XML file looks like below: `

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<server>
    <server01>
       <department>A1</department>
       <department>A2</department> 
    </server01>
    <server02>
       <department>A1</department>
       <department>A2</department> 
    </server02>
</server>

Is there a possiblity to read in Java elements between <server01> and <server02>, excluding rest of file? Or I need to use different tags? I found method how to read parentnodes:

NodeList serversNames = xmlD.getDocumentElement().getChildNodes();

for (int i = 0; i < serversNames.getLength(); i++) {
    Node node = serversNames.item(i);
    if (node instanceof Element) {
        Element childElement = (Element) node;
        System.out.println("tag name: " + childElement.getTagName());
    }
}

I am able to read all departments tags and save them to array:

NodeList serverName = xmlD.getElementsByTagName("department");

serversList = new String[serverName.getLength()];

System.out.println("zasieg: " + serverName.getLength());

for (int temp = 0; temp < serverName.getLength(); temp++) {
    Element shareName = null;

    shareName = (Element) serverName.item(temp);

    serversList[temp] = shareName.getTextContent();
    System.out.println(temp + " - " + serversList[temp]);
}

So, again, is there a possibility to read elements of parent node only? Elements of SERVER01 only?

Joel
  • 19,175
  • 2
  • 63
  • 83
xeen
  • 13
  • 1
  • 2
  • Are you saying you want to stop reading the document after you have read the contents of and so not read in the contents of ? I think you need to define that logic in your program, it won't really be part of any XML parser. – Matt N Sep 30 '13 at 18:31
  • 1
    It's not clear what you're trying to do or what the issue is. Can't you just use XPath or the equivalent? If you use an event-driven parser you can stop whenever you want, if it's really worth it. – Dave Newton Sep 30 '13 at 18:32
  • you can use xstream to convert to XML to object and object to XML, Its very easy way to convert XML to object and object to XML. – cvsr.sarma Sep 30 '13 at 18:42
  • Here is a useful reference: http://viralpatel.net/blogs/java-xml-xpath-tutorial-parse-xml/ – Rajesh Sep 30 '13 at 18:43
  • 1
    @MattN: Not true. There are 2 methods of parsing XML markup: DOM (read the whole file into a tree data structure) and SAX (stream in the file and handle tags as they are encountered during parsing). Sounds like a SAX-based xml parsing approach with early termination would suit the OP's needs nicely. See http://stackoverflow.com/questions/6828703/difference-about-sax-and-dom – Asaph Sep 30 '13 at 18:44

1 Answers1

3

XPath is what you want. For all intents and purposes, you can think of xpath as you would sql, only it is for xml documents instead of databases. Here is a simple example using Java (keep in mind xpath is a standard and not specific to java, so you can find many ways of doing this in pretty much any popular language):

    // Load document
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document doc = builder.parse( new FileInputStream( "/tmp/xml" ) );

    // Create XPath expression
    XPathFactory xPathfactory = XPathFactory.newInstance();
    XPath xpath = xPathfactory.newXPath();
    XPathExpression expr = xpath.compile( "//server01" );

    // Find node 'server01'
    Node node = (Node) expr.evaluate( doc, XPathConstants.NODE );
    if( node == null ) {
        System.out.println( "Node not found" );
        System.exit( 0 );
    }

    // Extract departments
    Element server01 = (Element) node;
    for( int k = 0 ; k < server01.getChildNodes().getLength() ; k++ ) {
        Node childNode = server01.getChildNodes().item( k );
        // Check if current node is a department node
        if( "department".equals( childNode.getNodeName() ) ) {
            System.out.println( childNode.getNodeName() + ": " + childNode.getTextContent().trim() );
        }
    }

Is there is a possibility to avoid this?

Yes just change XPath expression an receive only nodes you need.

// Load document
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse( new FileInputStream( "/tmp/xml" ) );

// Create XPath expression
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile( "//server01/department" );

// Find nodes 'department' under node 'server01'
NodeList node = (NodeList) expr.evaluate( doc, XPathConstants.NODESET );

// Extract departments
for( int k = 0 ; k < node.getLength() ; k++ ) {
    Node childNode = node.item( k );
    // Check if current node is a department node
    if( "department".equals( childNode.getNodeName() ) ) {
        System.out.println( "[" + k + "] " + childNode.getNodeName() + ": " + childNode.getTextContent().trim() );
    }
}

You must receive the next output:

[0] department: A1
[1] department: A2
Nicolai
  • 5,489
  • 1
  • 24
  • 31
  • To ensure I'm not taking points from you as a result of my edits, I've deleted my answer and gave you an upvote since we basically had the same answer. – Dave Sep 30 '13 at 18:59
  • Hi. This is a first simple solution. I am not surprised that I was not alone :) – Nicolai Sep 30 '13 at 19:02
  • Thanks! It is very helpful :). But, there is one thing, that is don;t understand. The output from program is: `null 1 - AP null 3 - AR null 5 - GL null 7 - CS null 9 - CL ` Why it count in that way? Not 1,2,3... but only the odd numbers? – xeen Oct 01 '13 at 18:05
  • Did you change original example? I've tested it and output shows correct lines: `department: A1` – Nicolai Oct 01 '13 at 18:09
  • You receive 'department' node on odd iterations because there are '#text' node with '\n' content between tags. – Nicolai Oct 01 '13 at 18:12
  • Is there is a possibility to avoid this? – xeen Oct 01 '13 at 18:17
  • Please look second variant in this answer. – Nicolai Oct 01 '13 at 18:26
  • Awesome :) Great thing! I am not able to give you a reputation point. Many thanks for this! – xeen Oct 01 '13 at 20:00