【问题标题】:Node.getTextContent() is there a way to get text content of the current node, not the descendant's textNode.getTextContent() 有没有办法获取当前节点的文本内容,而不是后代的文本
【发布时间】:2012-08-24 20:36:59
【问题描述】:

Node.getTextContent() 返回当前节点及其后代的文本内容。

有没有办法获取当前节点的文本内容,而不是后代的文本。

例子

<paragraph>
    <link>XML</link>
    is a 
    <strong>browser based XML editor</strong>
    editor allows users to edit XML data in an intuitive word processor.
</paragraph>

预期输出

paragraph = is a editor allows users to edit XML data in an intuitive word processor.
link = XML
strong = browser based XML editor

我试过下面的代码

String str =            "<paragraph>"+
                            "<link>XML</link>"+
                            " is a "+ 
                            "<strong>browser based XML editor</strong>"+
                            "editor allows users to edit XML data in an intuitive word processor."+
                        "</paragraph>";

        org.w3c.dom.Document domDoc = null;
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder;

        try {
            docBuilder = docFactory.newDocumentBuilder();
            ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
            domDoc = docBuilder.parse(bis);         
        } catch (ParserConfigurationException e1) {         
            e1.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }       

        DocumentTraversal traversal = (DocumentTraversal) domDoc;
        NodeIterator iterator = traversal.createNodeIterator(
                domDoc.getDocumentElement(), NodeFilter.SHOW_ELEMENT, null, true);

        for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {           
            String tagname = ((Element) n).getTagName();
            System.out.println(tagname + "=" + ((Element)n).getTextContent());
        }

但它给出了这样的输出

paragraph=XML is a browser based XML editoreditor allows users to edit XML data in an intuitive word processor.
link=XML
strong=browser based XML editor

注意 paragraph 元素包含 linkstrong 标签的文本,这是我不想要的。 请提出一些想法?

【问题讨论】:

    标签: java xml dom


    【解决方案1】:

    您想要过滤节点&lt;paragraph&gt; 的子节点,只保留节点类型为Node.TEXT_NODE 的子节点。

    这是返回所需内容的方法示例

    public static String getFirstLevelTextContent(Node node) {
        NodeList list = node.getChildNodes();
        StringBuilder textContent = new StringBuilder();
        for (int i = 0; i < list.getLength(); ++i) {
            Node child = list.item(i);
            if (child.getNodeType() == Node.TEXT_NODE)
                textContent.append(child.getTextContent());
        }
        return textContent.toString();
    }
    

    在您的示例中,这意味着:

    String str = "<paragraph>" + //
            "<link>XML</link>" + //
            " is a " + //
            "<strong>browser based XML editor</strong>" + //
            "editor allows users to edit XML data in an intuitive word processor." + //
            "</paragraph>";
    Document domDoc = null;
    try {
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
        ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
        domDoc = docBuilder.parse(bis);
    } catch (Exception e) {
        e.printStackTrace();
    }
    DocumentTraversal traversal = (DocumentTraversal) domDoc;
    NodeIterator iterator = traversal.createNodeIterator(domDoc.getDocumentElement(), NodeFilter.SHOW_ELEMENT, null, true);
    for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {
        String tagname = ((Element) n).getTagName();
        System.out.println(tagname + "=" + getFirstLevelTextContent(n));
    }
    

    输出:

    paragraph= is a editor allows users to edit XML data in an intuitive word processor.
    link=XML
    strong=browser based XML editor
    

    它的作用是迭代节点的所有子节点,只保留 TEXT(因此不包括 cmets、节点等)并累积它们各自的文本内容。

    NodeElement 中没有直接获取第一级文本内容的方法。

    【讨论】:

      【解决方案2】:

      如果您将最后一个 for 循环更改为以下循环,它的行为将如您所愿

      for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {           
          String tagname = ((Element) n).getTagName();
          StringBuilder content = new StringBuilder();
          NodeList children = n.getChildNodes();
          for(int i=0; i<children.getLength(); i++) {
              Node child = children.item(i);
              if(child.getNodeName().equals("#text"))
                  content.append(child.getTextContent());
          }
          System.out.println(tagname + "=" + content);
      }
      

      【讨论】:

        【解决方案3】:

        我使用 Java 8 流和一个辅助类来做到这一点:

        import java.util.*;
        import org.w3c.dom.Node;
        import org.w3c.dom.NodeList;
        
        public class NodeLists
        {
            /** converts a NodeList to java.util.List of Node */
            static List<Node> list(NodeList nodeList)
            {
                List<Node> list = new ArrayList<>();
                for(int i=0;i<nodeList.getLength();i++) {list.add(nodeList.item(i));}
                return list;
            }
        }
        

        然后

         NodeLists.list(node)
        .stream()
        .filter(node->node.getNodeType()==Node.TEXT_NODE)
         .map(Node::getTextContent)
         .reduce("",(s,t)->s+t);
        

        【讨论】:

        • 使用你的代码“原样” - 得到The method filter((&lt;no type&gt; node) -&gt; {}) is undefined for the type List&lt;Node&gt;的编译器错误
        • 这是 3 年后,但我想我在 . filter(... 之前忘记了 .stream()
        • 当你很好!解决了它,感谢我是 Java 8 和流功能的新手。再次感谢您的帮助和快速响应-我希望您的回答对我有所帮助,因为我遇到了与原始 OP 相同的问题!祝你晚上愉快,祝你的博士好运!
        【解决方案4】:

        对于实际的节点文本隐含地没有任何功能,但通过一个简单的技巧你可以做到。询问 node.getTextContent() 是否包含“\n”,如果是,则实际节点没有任何文本。

        希望对您有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-02-20
          • 1970-01-01
          • 1970-01-01
          • 2014-07-23
          • 1970-01-01
          • 1970-01-01
          • 2022-06-16
          • 1970-01-01
          相关资源
          最近更新 更多