使用 NodeList 遍历 XML 中的所有元素
Posted
技术标签:
【中文标题】使用 NodeList 遍历 XML 中的所有元素【英文标题】:Loop through all elements in XML using NodeList 【发布时间】:2013-01-12 01:27:27 【问题描述】:我想遍历一段 XML 中的所有元素,打印每个元素。我的问题是我在staff1
标记之后不断收到空指针异常,即john 465456433 gmail1 area1 city1
这是我的 Java 代码,用于打印 xml 文件中的所有元素:
File fXmlFile = new File("file.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
NodeList nList = doc.getElementsByTagName("*");
System.out.println("----------------------------");
Node n=null;
Element eElement=null;
for (int i = 0; i < nList.getLength(); i++)
System.out.println(nList.getLength());
n= nList.item(i);
System.out.println("\nCurrent Element :" + n.getNodeName());
if (n.getNodeType() == Node.ELEMENT_NODE)
eElement = (Element) n.getChildNodes();
System.out.println("\nCurrent Element :" + n.getNodeName());
name = eElement.getElementsByTagName("name").item(i).getTextContent(); //here throws null pointer exception after printing staff1 tag
phone = eElement.getElementsByTagName("phone").item(i).getTextContent();
email = eElement.getElementsByTagName("email").item(i).getTextContent();
area = eElement.getElementsByTagName("area").item(i).getTextContent();
city = eElement.getElementsByTagName("city").item(i).getTextContent();
n.getNextSibling();
XML 文件:
<?xml version="1.0"?>
<company>
<staff1>
<name>john</name>
<phone>465456433</phone>
<email>gmail1</email>
<area>area1</area>
<city>city1</city>
</staff1>
<staff2>
<name>mary</name>
<phone>4655556433</phone>
<email>gmail2</email>
<area>area2</area>
<city>city2</city>
</staff2>
<staff3>
<name>furvi</name>
<phone>4655433</phone>
<email>gmail3</email>
<area>area3</area>
<city>city3</city>
</staff3>
</company>
预期输出:
john
465456433
gmail1
area1
city1
mary
4655556433
gmail2
area2
city2
furvi
4655433
gmail3
area3
city3
【问题讨论】:
你得到的实际输出是多少? 在哪一行抛出 NullPointerException? 对于通配符,您需要 XPath。 获得staff1标签后我的意思是(john 465456433 gmail1 area1 city1)它在名称字段上抛出空指针异常 【参考方案1】: DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document dom = db.parse("file.xml");
Element docEle = dom.getDocumentElement();
NodeList nl = docEle.getChildNodes();
int length = nl.getLength();
for (int i = 0; i < length; i++)
if (nl.item(i).getNodeType() == Node.ELEMENT_NODE)
Element el = (Element) nl.item(i);
if (el.getNodeName().contains("staff"))
String name = el.getElementsByTagName("name").item(0).getTextContent();
String phone = el.getElementsByTagName("phone").item(0).getTextContent();
String email = el.getElementsByTagName("email").item(0).getTextContent();
String area = el.getElementsByTagName("area").item(0).getTextContent();
String city = el.getElementsByTagName("city").item(0).getTextContent();
遍历所有子节点,nl.item(i).getNodeType() == Node.ELEMENT_NODE
用于过滤掉文本节点。如果 XML 中没有其他内容,那么剩下的就是人员节点。
对于 stuff 下的每个节点(姓名、电话、电子邮件、区域、城市)
el.getElementsByTagName("name").item(0).getTextContent();
el.getElementsByTagName("name")
将提取 stuff 下的“name”节点,
.item(0)
将为您提供第一个节点
.getTextContent()
将获取里面的文本内容。
编辑: 既然我们有杰克逊,我会以不同的方式做到这一点。为对象定义一个 pojo:
public class Staff
private String name;
private String phone;
private String email;
private String area;
private String city;
...getters setters
然后使用杰克逊:
JsonNode root = new XmlMapper().readTree(xml.getBytes());
ObjectMapper mapper = new ObjectMapper();
root.forEach(node -> consume(node, mapper));
private void consume(JsonNode node, ObjectMapper mapper)
try
Staff staff = mapper.treeToValue(node, Staff.class);
//TODO your job with staff
catch (JsonProcessingException e)
e.printStackTrace();
【讨论】:
谢谢你能为所有元素制作代码的第一部分nl.getLength() > 0
不是必需的,因为它无论如何都不会进入循环。
请注意,NodeList 上的 getLength 可能非常慢,具体取决于实现方式。例如,请参阅sourceforge.net/p/findbugs/feature-requests/317。最好在遍历 NodeList 之前将长度存储在变量中。【参考方案2】:
public class XMLParser
public static void main(String[] args)
try
DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = dBuilder.parse(new File("xml input"));
NodeList nl=doc.getDocumentElement().getChildNodes();
for(int k=0;k<nl.getLength();k++)
printTags((Node)nl.item(k));
catch (Exception e) /*err handling*/
public static void printTags(Node nodes)
if(nodes.hasChildNodes() || nodes.getNodeType()!=3)
System.out.println(nodes.getNodeName()+" : "+nodes.getTextContent());
NodeList nl=nodes.getChildNodes();
for(int j=0;j<nl.getLength();j++)printTags(nl.item(j));
递归循环并打印出文档中的所有 xml 子标签,以防您不必更改代码来处理 xml 中的动态更改,前提是它是格式良好的 xml。
【讨论】:
【参考方案3】:这是使用 JDOM 循环遍历 XML 元素的另一种方法。
List<Element> nodeNodes = inputNode.getChildren();
if (nodeNodes != null)
for (Element nodeNode : nodeNodes)
List<Element> elements = nodeNode.getChildren(elementName);
if (elements != null)
elements.size();
nodeNodes.removeAll(elements);
【讨论】:
这太容易了。 XML 意味着很难。【参考方案4】:NodeList listaHijos = docEle.getChildNodes();
listaHijos = listaHijos.item(2).getChildNodes();
for (int i = 0; i < listaHijos.getLength(); i++)
eElement = (Element) listaHijos.item(i);
n2 = eElement.getChildNodes();
for (int j = 0; j < n2.getLength(); j++)
System.out.println("elem:" + n2.item(j).getNodeName() + " :" + n2.item(j).getTextContent() + "j" + j);
if (n2.item(j).getNodeName().equals("detallesAdicionales"))
eElement = (Element) n2.item(j);
n6 = eElement.getChildNodes();
System.out.println("todo: " + n6.item(0).getAttributes().item(0) + n6.item(0).getAttributes().item(1));
System.out.println("todo2: " + n6.item(1).getAttributes().item(0) + n6.item(1).getAttributes().item(1));
System.out.println("todo3: " + n6.item(2).getAttributes().item(0) + n6.item(2).getAttributes().item(1));
System.out.println("nombre: " + n6.item(0).getAttributes().item(0).getTextContent());
System.out.println("valor: " + n6.item(0).getAttributes().item(1).getTextContent());
【讨论】:
您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。以上是关于使用 NodeList 遍历 XML 中的所有元素的主要内容,如果未能解决你的问题,请参考以下文章