0

This is the XML file I'm working on:

<book>
    <chapter index="1" name="Chapter 2">
        <verse index="1" text="First Line" />
        <verse index="2" text="Second Line" />
        <verse index="3" text="Third Line" />
    </chapter>
    <chapter index="1" name="Chapter 2">
        <verse index="1" text="First Line" />
        <verse index="2" text="Second Line" />
        <verse index="3" text="Third Line" />
    </chapter>
</book>

This is what I desperately tried, following an answer posted: How can I read Xml attributes using Java?

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;


public class Main
{
    public static void main (String[] args)
    {
        try
        {
            File fXmlFile = new File("book.xml");
             DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
             DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
             Document doc = dBuilder.parse(fXmlFile);
             doc.getDocumentElement().normalize();

             System.out.println("Verse: " +
                     doc.getDocumentElement().getElementsByTagName("chapter").item(0).getChildNodes().item(0).getAttributes().getNamedItem("text").getNodeValue());

        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }
}

I tried to print the first verse of each chapter, but got a Null Pointer exception

Community
  • 1
  • 1
Moh
  • 23
  • 1
  • 5

4 Answers4

2

The API you're using treats the whitespaces between the tags as seperate nodes. If you print the node names of child nodes of the first chapter using this code:

NodeList lst = doc.getDocumentElement().getElementsByTagName("chapter").item(0).getChildNodes();

for (int i = 0; i < lst.getLength(); i++) {
    System.out.println(lst.item(i).getNodeName());
}

you'll get:

#text
verse
#text
verse
#text
verse
#text

Which means that the node at index 0 is not the verse node, but a text node, that contains no attributes, which causes a NPE, since you try to call a method of the non existent attribute object (null).

If you delete the whitespaces before the verse node like this:

<book>
    <chapter index="1" name="Chapter 2"><verse index="1" text="First Line" />
...

, everything works fine.

But you better use getElementsByTagName("verse") to get the verse nodes, that are child nodes of the chapter:

System.out.println("Verse: "
                    + ((Element)doc.getDocumentElement().getElementsByTagName("chapter").item(0)).getElementsByTagName("verse").item(0).getAttributes().getNamedItem("text").getNodeValue());
fabian
  • 80,457
  • 12
  • 86
  • 114
1

you may choose the possibility of using dom4j. its quite straight forward

Straight from dom4j

   public void treeWalk(Document document) {
        treeWalk( document.getRootElement() );
    }

    public void treeWalk(Element element) {
        for ( int i = 0, size = element.nodeCount(); i < size; i++ ) {
            Node node = element.node(i);
            if ( node instanceof Element ) {
                treeWalk( (Element) node );
            }
            else {
                // do something....
            }
        }
    }

then all you need to do is choosing attributes by adding a condition such as :

 ....
 if ( node instanceof Element ) {
    //condition goes here:: e.g.
    if(node.getParent().getName().equals("chapter") && node.getName().equals("verse"){
       if (node.attribute("index").getData().toString().equals("1"))
          System.out.println(node.attribute(text).getDate().toString());
    }
    treeWalk( (Element) node );
 }

output:

First Line
First Line
nafas
  • 5,283
  • 3
  • 29
  • 57
0

You can read it like this to read first verse of each chapter:

         NodeList chapters = doc.getElementsByTagName("chapter");

         for(int i=0;i < chapters.getLength();i++) {
             Element chapter = (Element) chapters.item(i);
             System.out.println("Chapter = " + chapter.getAttribute("name"));
             Element verse = (Element) chapter.getElementsByTagName("verse").item(0);
             System.out.println(verse.getAttribute("text"));
         }
Sanjeev
  • 9,876
  • 2
  • 22
  • 33
0
NodeList listOfChapter = doc.getElementsByTagName("chapter");

NodeList listofVerse = doc.getDocumentElement().getElementsByTagName("chapter").item(0).getChildNodes(); 

for (int j = 0; j < listOfChapter.getLength(); j++) {
    for (int i = 0; i < listofVerse.getLength() / listOfChapter.getLength(); i++) {
        Element chapter = (Element) listOfChapter.item(j);
        System.out.println("Chapter = " + chapter.getAttribute("name"));
        System.out.println("Index: " + ((Element) doc.getDocumentElement().getElementsByTagName("chapter").item(j)).getElementsByTagName("verse").item(i).getAttributes().getNamedItem("index").getNodeValue());
        System.out.println("Verse: " + ((Element) doc.getDocumentElement().getElementsByTagName("chapter").item(j)).getElementsByTagName("verse").item(i).getAttributes().getNamedItem("text").getNodeValue());
    }
}
Lukas Körfer
  • 13,515
  • 7
  • 46
  • 62
  • Output: run: Chapter = Chapter 2 Index: 1 Verse: First Line Chapter = Chapter 2 Index: 2 Verse: Second Line Chapter = Chapter 2 Index: 3 Verse: Third Line Chapter = Chapter 3 Index: 1 Verse: First Line Chapter = Chapter 3 Index: 2 Verse: Second Line Chapter = Chapter 3 Index: 3 Verse: Third Line – Camila Paiva Apr 24 '17 at 14:35
  • Please add an explanation to your answer, as code-only answers cannot improve the askers comprehension on the topic. – Lukas Körfer Apr 24 '17 at 14:44