如何在xml解析中检查Nodelist是否有标签?

时间:2015-04-20 13:02:27

标签: java xml parsing java-ee xml-parsing

我正在解析一个动态生成的xml,我对从xml中提取数据有一些疑问。我的代码如下,

    try {
      File file = new File("test.xml");
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.parse(file);
      doc.getDocumentElement().normalize();
      System.out.println("Root element " + doc.getDocumentElement().getNodeName());
      NodeList nodeLst = doc.getElementsByTagName("control");
      System.out.println("Information of all fields");

      for (int s = 0; s < nodeLst.getLength(); s++) {

        Node fstNode = nodeLst.item(s);

        if (fstNode.getNodeType() == Node.ELEMENT_NODE) {

          Element fstElmnt = (Element) fstNode;


                  NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("value");
              Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
              NodeList fstNm = fstNmElmnt.getChildNodes();
              System.out.println("Value:  "  + ((Node) fstNm.item(0)).getNodeValue());


                  NodeList lstNmElmntLst = fstElmnt.getElementsByTagName("label");
              Element lstNmElmnt = (Element) lstNmElmntLst.item(0);
              NodeList lstNm = lstNmElmnt.getChildNodes();
              System.out.println("Label: " + ((Node) lstNm.item(0)).getNodeValue());

NodeList hintElmntLst = fstElmnt.getElementsByTagName("hint");
          Element hintElmnt = (Element) hintElmntLst.item(0);
          NodeList hint = hintElmnt.getChildNodes();
          System.out.println("Hint: " + ((Node) hint.item(0)).getNodeValue());

        }

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

我的XML格式

    <metadata>

    <control name="first-name">
    <resources lang="en">
    <label>First Name</label>
    <hint>your first name</hint>

    </resources>
<resources lang="fr">
                            <label>Prénom</label>
                            <help />
                            <hint>
                                    Votre prénom
                            </hint>

                    </resources>
<value> Hari </value>
    </control>


    </metadata>

我有以下问题,

1)如果相应字段存在提示,则只有<hint>存在于xml中,否则它不会退出。因此,如果标签不存在,那么我得到错误。那么我们如何检查标签是否存在?如果标签存在,那么我们将获得标签内容。

2)对于值字段如果字段值不为null,那么它将正常工作。如果字段值为null,则xml中的标记将显示为<value/>,因此如果字段值为null,则我的代码未检测到<value/>标记并收到错误。那么如果字段值带有空值,我怎么能将字段值设置为null。

请提出任何建议..

3 个答案:

答案 0 :(得分:3)

你只需要检查你得到的元素节点。

如果您有<value />,那么它将没有子节点:

  NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("value");
  Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
  if (fstNmElmnt.hasChildNodes()) {
      NodeList fstNm = fstNmElmnt.getChildNodes();
      System.out.println("Value:  "  + ((Node) fstNm.item(0)).getNodeValue());
  } else {
      System.out.println("Value: null");
  }

如果您没有提示,那么您将获得0长度列表:

  NodeList hintElmntLst = fstElmnt.getElementsByTagName("hint");
  if (hintElmntLst.getLength() > 0) {
      Element hintElmnt = (Element) hintElmntLst.item(0);
      NodeList hint = hintElmnt.getChildNodes();
      System.out.println("Hint: " + ((Node) hint.item(0)).getNodeValue());
  }

回答评论问题:如果您只想阅读英文资源,那么只需在您所拥有的内容中引入另一个循环:

  NodeList resources = fstElmnt.getElementsByTagName("resources");
  for (int k = 0; k < resources.getLength(); k++) {
      Node resNode = resources.item(k);
      if (resNode.getNodeType() == Node.ELEMENT_NODE) {
          Element resElement = (Element)resNode;
          if (resElement.hasAttribute("lang") &&
                   resElement.getAttribute("lang").equals("en")) {
              //your existing code here for value, label, hint
          }
      }
   }

您只需更改代码的值,标签和提示,以便只访问resElement。例如:

NodeList fstNmElmntLst = resElement.getElementsByTagName("value");

而不是fstElmnt.getElementsByTagName("value");

答案 1 :(得分:1)

没关系?如果我改变它如下;

而不是这个;

          NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("value");
          Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
          NodeList fstNm = fstNmElmnt.getChildNodes();
          System.out.println("Value:  "  + ((Node) fstNm.item(0)).getNodeValue());

改变它;

         System.out.println("Value:  " + getTagValue("value", fstElmnt) );

getTagValue方法是;

private static String getTagValue(String tag, Element eElement) {
    Node nNode = eElement.getElementsByTagName(tag).item(0);
    if (nNode == null) {
        return null;
    }
    NodeList nlList = nNode.getChildNodes();
    Node nValue = (Node) nlList.item(0);
    if (nValue == null)
        return null;
    return nValue.getNodeValue();
}

答案 2 :(得分:1)

改用XPath。代码将很多更易于阅读和维护:

    XPath xp = XPathFactory.newInstance().newXPath();

    NodeList controls = (NodeList) xp.evaluate("//control", doc,
            XPathConstants.NODESET);
    for (int i = 0; i < controls.getLength(); ++i) {
        Node c = controls.item(i);
        String label = xp.evaluate(".//label", c);
        String hint = xp.evaluate(".//hint", c);
        String value = xp.evaluate(".//value", c);

        System.out.printf("%s, %s, %s\n", label, hint, value);
    }

更新:

要根据语言进行选择,只需在资源元素中包含谓词:

        String label = xp.evaluate("resources[@lang='en']/label", c);
        String hint = xp.evaluate("resources[@lang='en']/hint", c);
        String value = xp.evaluate("resources[@lang='en']/value", c);

或者,您当然可以选择resources元素,然后选择每个所需的子元素。