为什么我的 XML 文件中会有 #text 节点?

10

我正在制作一个Android应用程序,对XML文件进行DOM解析。我有一个像这样的XML文件:

<?xml version="1.0" encoding="utf-8"?>
<family>
    <grandparent>
        <parent1>
            <child1>Foo</child1>
            <child2>Bar</child2>
        </parent1>
        <parent2>
            <child1>Raz</child1>
            <child2>Mataz</child2>
        </parent2>
    </grandparent>  
</family>

如果我对它运行一个DOM解析器,就像这样:

try {
    DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        
    Document doc = builder.parse(input);
    doc.getDocumentElement().normalize();   //added in since the edit
    NodeList nodd = doc.getElementsByTagName("grandparent");
    for (int x = 0; x < nodd.getLength(); x++){
        Node node = nodd.item(x);
        NodeList nodes = node.getChildNodes();
        for(int y = 0; y < nodes.getLength(); y++){
            Node n = nodes.item(y);
            System.out.println(n.getNodeName());
        }
    }
}

我的应用程序打印出以下内容

07-20 18:24:28.395: INFO/System.out(491): #text

07-20 18:24:28.395: INFO/System.out(491): parent1

07-20 18:24:28.395: INFO/System.out(491): #text

07-20 18:24:28.395: INFO/System.out(491): parent2

07-20 18:24:28.395: INFO/System.out(491): #text

我的问题是,这些 #text 是什么,更重要的是,我该如何去掉它们?

编辑:现在我知道它们是什么了,我尝试对其进行规范化。 我已更新代码以反映更改,但结果相同。

3个回答

8
这是空白字符(换行符、空格、制表符) :)

我该如何检查它?我想我可以使用 getNextSibling(),但我能否保证它总是有一个 #text 作为第一个子节点? - Otra
你不能指望 #text 是第一个节点,因为后面可能还有其他节点。不过,你说的移除是什么意思呢?如果你正在收集所有节点并将它们输出到某个地方,只需在生成节点时检查每个节点,查看其类型,如果是 #text 并且内容全为空白字符,就不要输出它。 - Ray Toal
我想说“removing”可能不太准确,因为我保证在#text所在的位置不会出现任何文本。但是你提到了我正在寻找的东西。我可以检查getNodeType()。谢谢。 - Otra
1
很高兴它能正常工作。我查了一下“normalize”的定义,它会完全删除空文本节点,但不会删除完全由空格组成的节点。所以忽略它们是正确的做法。 - Ray Toal

1
这是你得到的内容:
1)一个节点列表,其中所有节点都是祖父节点
NodeList nodd = doc.getElementsByTagName("grandparent");

2)所有父级为x的子节点

NodeList nodes = node.getChildNodes();

哪些是子节点?

< grandparent >
    < parent1 >
       ...
    < /parent1 >

    < parent2 >
       ...
    < /parent2 >
< /grandparent >

3) 子代 y

nodes.item(y);

在这里可能会有一些文本,而这是你所拥有的 #文本,如果你有:

< grandparent >
    yourTextHere1
    < parent1 >
       ...
    < /parent1 >
    yourTextHere2
    < parent2 >
       ...
    < /parent2 >
    yourTextHere3
< /grandparent >

你会得到:

你的文本1 父级1 你的文本2 父级2 你的文本3

希望对你有所帮助! 朱利安,


那么我该如何去除文本子元素或测试文本子元素? - Otra
文档 doc = builder.parse(input); doc.getDocumentElement().normalize(); - jmartel
这是我在想的,但我能确定它们总是间隔一个吗? - Otra
我认为是的,如果不是,那就意味着它没有以XML格式进行格式化。可能还有其他的解决方案(我不知道),但这是我使用过且至今从未出现问题的方法。 - jmartel
我也发现了这个问题,根据你使用的解析器,可能会有一个名为bool isContentWhiteSpace()的函数或者一个属性可以获取... 可以参考这个链接:http://www.w3schools.com/Dom/dom_text.asp - jmartel
是的,我之前没有意识到有一个 getNodeType() 函数,它可以告诉你它是元素还是文本子节点,所以现在我在使用它。 - Otra

0

解析文档时,请执行以下操作:

Document doc = builder.parse(input); 
doc.getDocumentElement().normalize();

这将会压缩XML文件并移除所有不需要的#text子元素。


4
我测试过了,但它没有生效。我仍然能看到 #text 子元素。 - Otra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接