使用Java读取包含特殊字符(&, - 等)的XML文档节点

时间:2012-02-04 03:47:51

标签: java xml parsing special-characters

我的代码不会检索包含特殊字符的整个元素节点。 例如,对于此节点:

<theaterName>P&G Greenbelt</theaterName>

由于&符号,它只会检索“P”。我需要检索整个字符串。

这是我的代码:

public List<String> findTheaters() {

    //Clear theaters application global
    FilmhopperActivity.tData.clearTheaters();

    ArrayList<String> theaters = new ArrayList<String>();

    NodeList theaterNodes = doc.getElementsByTagName("theaterName");

    for (int i = 0; i < theaterNodes.getLength(); i++) {

        Node node = theaterNodes.item(i);
        if (node.getNodeType() == Node.ELEMENT_NODE) {

            //Found theater, add to return array
            Element element = (Element) node;
            NodeList children = element.getChildNodes();
            String name = children.item(0).getNodeValue();
            theaters.add(name);

            //Logging
            android.util.Log.i("MoviefoneFetcher", "Theater found: " + name);

            //Add theater to application global
            Theater t = new Theater(name);
            FilmhopperActivity.tData.addTheater(t);
        }
    }

    return theaters;
}

我尝试添加代码来扩展名称字符串以连接其他的children.items,但它不起作用。我只会得到“P&amp;”。

...
String name = children.item(0).getNodeValue();
for (int j = 1; j < children.getLength() - 1; j++) {
    name += children.item(j).getNodeValue();
}

感谢您的时间。


更新: 找到一个名为normalize()的函数,你可以在Nodes上调用它,它结合了所有文本子节点,所以做一个children.item(0)包含所有孩子的文本,包括&符号!

4 个答案:

答案 0 :(得分:5)

&是XML中的转义字符。看起来像这样的XML:

<theaterName>P&G Greenbelt</theaterName>

实际上应该被解析器拒绝。相反,它应该是这样的:

<theaterName>P&amp;G Greenbelt</theaterName>

有一些此类字符,例如<(&amp; lt;),>(&amp; gt;),"(&amp; quot;)和{{ 1}}(&amp;)。还有其他方法来转义字符,例如通过它们的Unicode值,如&amp;#x2022;或&amp;#12345;。

有关详细信息,XML specification非常明确。

现在,根据你的树的构造方式,它可能是另一件事,就是 正确地转义了,你展示的样本并不是实际存在的样本,而是它的方式数据在树中表示。

例如,当使用SAX构建树时,实体(' - thingies)会被拆分并单独交付。这是因为SAX解析器尝试返回连续的数据块,当它到达转义字符时,它会发送它所拥有的内容,并启动一个带有翻译的& - 值的新块。因此,您可能需要在树中组合连续的文本节点以获得整个值。

答案 1 :(得分:2)

您尝试阅读的文件不是有效的XML。没有自尊的XML解析器会接受它。

  

我正在从网上动态检索我的XML。获取Document对象后,替换所有转义字符的最佳方法是什么?

你采取了错误的做法。正确的方法是通知负责创建该文件无效的人员,并请求他们修复该文件。简单地编写黑客(尝试)修复损坏的XML并不符合您(或其他人的长期兴趣)。

如果您决定忽略此建议,那么一个方法是将文件读入字符串,使用String.replaceAll(正则表达式,更换)与合适的正则表达式来将这些虚假"&"字符到正确字符实体("&amp;"),然后将固定的XML字符串提供给XML解析器。您需要仔细设计正则表达式,以便它不会将有效的字符实体破坏为不必要的副作用。第二种方法是手动进行解析和替换,使用适当的启发式方法将伪造的"&"字符与格式良好的字符实体区分开来。

但这一切都会花费你的开发和测试时间,并减慢你的软件速度。更糟糕的是,由于您努力补偿错误的输入文件,因此您的代码很脆弱。 (并猜猜谁会受到指责......)

答案 2 :(得分:0)

您需要正确编码或将其包装在CDATA部分中。我推荐前者。

答案 3 :(得分:0)

数字字符引用"&#60;""&#38;"可用于在字符数据中出现&lt; &amp; 。<登记/> 所有XML处理器必须识别这些实体是否被声明。对于interoperability,有效的XML文档在使用之前应该像其他实体一样声明这些实体。如果声明了实体ltamp,则必须将其声明为internal entities,其替换文字为 character reference 至相应的字符(较少) -than sign或&ersand)被转义; 这些实体的双重转义是REQUIRED,因此对它们的引用会产生格式良好的结果。如果声明了实体gtaposquot,则必须声明为internal entities,其替换文字是转义的单个字符(或者对该字符的字符引用;此处的双重转义是可选的但无害的)。例如:

<!ENTITY lt     "&#38;#60;">
<!ENTITY gt     "&#62;">
<!ENTITY amp    "&#38;#38;">
<!ENTITY apos   "&#39;">
<!ENTITY quot   "&#34;">