【问题标题】:.getTextContent returns text from child elements too.getTextContent 也从子元素返回文本
【发布时间】:2015-05-15 17:22:27
【问题描述】:

我正在尝试对 XML 进行解析(是的,我知道有更简单的方法可以像 xstream 那样解析/验证),但我似乎无法仅获取单个元素的文本内容。例如:

<container>
   <element0>textThatIWant</element0> //only returned by .getTextContent
   <element1>
      <subelement0>textThatIDontWant</subelement0> //but also returned by
      <subelement1>textThatIDontWant</subelement1> //.getTextContent
   </element1>
<container>

我将结果输出到控制台,主要得到我正在寻找的内容,但我似乎获得文本字符串的唯一方法是使用.getTextContent(),它也返回子元素中的所有文本,没有空格(否则我会在空格上拆分)或.getNodeValue().toString(),它会抛出nullPointerExceptions。 @Jihar 提到了 .getTextValue() 之类的东西,但 Eclipse 无法识别它(也许我可以实现/继承/添加任何功能),有什么帮助吗?

这是我正在使用的代码:

import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;

public class Test {
   public static void main(String[] args) throws  ParserConfigurationException, SAXException, IOException {
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder = factory.newDocumentBuilder();
      StringBuilder xmlStringBuilder = new StringBuilder();
      String appendage = "..." //This string holds the xml formatted data I'll be 
                               //using in a long annoying line, I'll include it 
                               //separately for clarity
      xmlStringBuilder.append(appendage);   
      ByteArrayInputStream input = new ByteArrayInputStream(xmlStringBuilder.toString().getBytes("UTF-8"));

      System.out.println("Test Results:");
      System.out.println();

      Document doc = builder.parse(input);
      Element root = doc.getDocumentElement();
      NodeList children = root.getChildNodes();

      System.out.println(root.getTagName());
      System.out.println();

      for (int i = 0; i < children.getLength(); i++) {
         Node child = children.item(i);
         if (child instanceof Element) { 
            Element childElement = (Element) child; 
            System.out.println(childElement.getTagName() + " " + childElement);

            NodeList grandChildren = child.getChildNodes();
            for (int x = 0; x < grandChildren.getLength(); x++) {
               Node grandChild = grandChildren.item(x);
               if (grandChild instanceof Element) {
                  Element grandChildElement = (Element) grandChild;
                  System.out.print("\t" + grandChildElement.getTagName() + ":\t");

                  NodeList greatGrandChildren = grandChild.getChildNodes();
                  for (int y = 0; y < greatGrandChildren.getLength(); y++) {
                     Node greatGrandChild = greatGrandChildren.item(y);
                     if (greatGrandChild instanceof Element) {
                        Element greatGrandChildElement = (Element) greatGrandChild;
                        System.out.print(" " + greatGrandChildElement.getTextContent());
                        if ( y < greatGrandChildren.getLength() - 1) { System.out.print(","); } }
                     }
                     System.out.println();
               }
            }
         }
      }
   }
}

这是完整的附加变量:

String appendage = "<?xml version=\"1.0\"?><branch0><name>business</name><taxINFO/><personnel><executives><name>Billy Bob</name><name>Colonel Jessup</name></executives><managerial/><operations><name>sabrina</name><name>lisa</name></operations><services><name>jamie</name><name>justin</name><name>forest</name></services></personnel><regions><ebay><area>OK</area><area>BE</area><area>EV</area><area>WC</area></ebay><sbay><area>SJ</area><area>MP</area><area>SV</area><area>MV</area></sbay><S.F.><area>SF</area></S.F.><N.Y.><area>NY</area></N.Y.><S.CA><area>SD</area><area>LA</area></S.CA></regions><products/><services/></branch0>";

或:

String appendage = "
<?xml version=\"1.0\"?>
<branch0>
   <name>business</name>
   <taxINFO/>
   <personnel>
      <executives>
         <name>Billy Bob</name>
         <name>Colonel Jessup</name>
      </executives>
   <managerial/>
   <operations>
      <name>sabrina</name>
      <name>lisa</name>
   </operations>
   <services>
      <name>jamie</name>
      <name>justin</name>
      <name>forest</name>
   </services>
   </personnel>
   <regions>
      <ebay>
         <area>OK</area>
         <area>BE</area>
         <area>EV</area>
         <area>WC</area>
      </ebay>
      <sbay>
         <area>SJ</area>
         <area>MP</area>
         <area>SV</area>
         <area>MV</area>
      </sbay>
      <S.F.>
         <area>SF</area>
      </S.F.>
      <N.Y.>
         <area>NY</area>
      </N.Y.>
      <S.CA>
         <area>SD</area>
         <area>LA</area>
      </S.CA>
   </regions>
   <products/>
   <services/>
</branch0>";
";

最后,我的控制台输出(您会看到[name: null] 我希望它说类似[name: business] 甚至只是business;但不包括不包含子元素数据空格):

Test Results:

branch0

name [name: null]
taxINFO [taxINFO: null]
personnel [personnel: null]
    executives:  Billy Bob, Colonel Jessup
    managerial: 
    operations:  sabrina, lisa
    services:    jamie, justin, forest
regions [regions: null]
    ebay:    OK, BE, EV, WC
    sbay:    SJ, MP, SV, MV
    S.F.:    SF
    N.Y.:    NY
    S.CA:    SD, LA
products [products: null]
services [services: null]

这是我使用.getTextContent的控制台输出:

Test Results:
business
branch0

name business
taxINFO 
personnel Billy BobColonel Jessupsabrinalisajamiejustinforest
 executives:     Billy Bob, Colonel Jessup
 managerial:    
 operations:     sabrina, lisa
 services:   jamie, justin, forest
regions OKBEEVWCSJMPSVMVSFNYSDLA
 ebay:   OK, BE, EV, WC
 sbay:   SJ, MP, SV, MV
 S.F.:   SF
 N.Y.:   NY
 S.CA:   SD, LA
products 
services 

【问题讨论】:

    标签: java xml string get element


    【解决方案1】:
    System.out.println(childElement.getTagName() + " " + childElement);
    

    应该是(如你所知!)

    System.out.println(childElement.getTagName() + " "
        + childElement.getTextContent());
    

    【讨论】:

    • 这是我使用的控制台结果:personnel Billy BobColonel Jessupsabrinalisajamiejustinforest executives: Billy Bob, Colonel Jessup managerial: operations: sabrina, lisa services: jamie, justin, forest regions OKBEEVWCSJMPSVMVSFNYSDLA ebay: OK, BE, EV, WC sbay: SJ, MP, SV, MV S.F.: SF N.Y.: NY S.CA: SD, LA
    • cmets 中的格式很奇怪,但基本上只有在没有子元素时才有效。
    • 我可以使用 .getNodeValue().toString 隔离我需要的文本,但我在测试空条件时遇到了麻烦(即使存在文本,NodeValue 似乎也是“空”,这让我觉得我错过了关于元素数据引用的一些东西?),所以空格会引发 nullPointerException
    • 根据定义,元素节点的“节点值”始终为空。如果您想要元素内的文本而不是其子元素内的文本,那么您必须遍历元素的子节点列表并仅处理那些是文本节点而不是元素节点的子节点。
    • 我很困惑,如果 NodeValue 根据定义为 null,为什么 .getNodeValue().toString() 会返回元素标签内的文本?我得到了返回的代码(我认为是十六进制字符)并使用 .toString() 将其格式化为正确的响应。 nodeValue 是否应该指代标签名称本身?另外,您能否包括一个解释您如何遍历子节点的答案?我还在想办法……
    【解决方案2】:

    因此,就我的目的而言,我能够使用 XPath 获取我正在寻找的各个元素:

    XPathFactory xpfactory = XPathFactory.newInstance();
    XPath path = xpfactory.newXPath();
    try {
        String aString = path.evaluate("/branch0/name", doc);
        System.out.println(aString);
        } catch (XPathExpressionException e) { e.printStackTrace(); }
    

    当然,这需要预先了解结构,但由于我可以使用 XML 模式进行验证,而且我的文档不是太复杂/嵌套太重,我认为这对我来说不是问题。当我完成当前项目的工作时,我将尝试查找并发布有关迭代子节点和检查文本节点的链接(正如@Ian Roberts 建议的那样),但我现在对 XML 的了解还不够。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-25
      • 2011-06-13
      • 1970-01-01
      • 2020-10-13
      • 1970-01-01
      • 2021-08-22
      相关资源
      最近更新 更多