这是我正在处理的XML文件:
<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>
根据发布的回答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();
}
}
}
答案 0 :(得分:2)
您正在使用的API将标记之间的空格视为单独的节点。如果使用以下代码打印第一章子节点的节点名称:
NodeList lst = doc.getDocumentElement().getElementsByTagName("chapter").item(0).getChildNodes();
for (int i = 0; i < lst.getLength(); i++) {
System.out.println(lst.item(i).getNodeName());
}
你会得到:
#text
verse
#text
verse
#text
verse
#text
这意味着索引0处的节点不是经文节点,而是一个文本节点,它不包含导致NPE的属性,因为您尝试调用不存在的属性对象的方法(null)。 / p>
如果你删除节点之前的空格,如下所示:
<book>
<chapter index="1" name="Chapter 2"><verse index="1" text="First Line" />
...
,一切正常。
但是你最好使用getElementsByTagName("verse")
来获取经文节点,这是节的子节点:
System.out.println("Verse: "
+ ((Element)doc.getDocumentElement().getElementsByTagName("chapter").item(0)).getElementsByTagName("verse").item(0).getAttributes().getNamedItem("text").getNodeValue());
答案 1 :(得分:1)
您可以选择使用dom4j的可能性。它很直接
直接来自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....
}
}
}
然后您需要做的就是通过添加条件来选择属性,例如:
....
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 );
}
输出:
First Line
First Line
答案 2 :(得分:0)
你可以这样阅读每章的第一节:
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"));
}
答案 3 :(得分: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());
}
}