【问题标题】:Reading XML document nodes containing special characters (&, -, etc) with Java使用 Java 读取包含特殊字符(&、- 等)的 XML 文档节点
【发布时间】:2012-02-26 15:17:17
【问题描述】:

我的代码没有检索到包含特殊字符的全部元素节点。 例如,对于这个节点:

<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&”。

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

感谢您的宝贵时间。


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

【问题讨论】:

  • 在 XML 内容中不允许使用 &,因此您尝试解析的 XML 无效。

标签: java xml parsing special-characters


【解决方案1】:

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

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

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

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

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

【讨论】:

    【解决方案2】:

    数字字符引用"&amp;#60;""&amp;#38;" 在字符数据中出现时可用于转义&
    所有XML 处理器必须识别这些实体,无论它们是否被声明。对于interoperability,有效的 XML 文档应该在使用它们之前声明这些实体,就像任何其他实体一样。如果实体 ltamp 被声明,它们必须声明为 internal entities 其替换文本是 character reference 到相应的字符(小于号或 & 号)被转义; 对于这些实体,双重转义是REQUIRED,以便对它们的引用产生格式良好的结果。如果声明了实体 gtaposquot,则它们必须声明为 internal entities,其替换文本是被转义的单个字符(或对该字符的字符引用; 这里的双重转义是可选的,但无害)。例如:

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

    【讨论】:

      【解决方案3】:

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

      <theaterName>P&G Greenbelt</theaterName>
      

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

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

      有几个这样的字符,例如&lt; (<)、&gt; (>)、" (") 和 ' (<)。还有其他方法可以转义字符,例如通过它们的 Unicode 值,如 •或 〹.

      更多信息,XML specification 相当清楚。

      现在,根据您的树的构造方式,另一件事可能是字符 正确转义,而您显示的示例不是实际存在的,而是如何数据在树中表示。

      例如,当使用 SAX 构建树时,实体(&amp;-thingies)被分解并单独交付。这是因为 SAX 解析器试图返回连续的数据块,当它到达转义字符时,它会发送它拥有的内容,并使用转换后的 &amp;-值开始一个新块。因此,您可能需要组合树中的连续文本节点来获取整个值。

      【讨论】:

      • 我正在从网络动态检索我的 XML。获取 Document 对象后替换所有转义字符的最佳方法是什么?
      • 请注意,quotapos 只能在用这些字符引用的属性中表示为实体。
      • @Dan 您获取的 XML 是否未转义?您应该让该 XML 的生产者更正它,因为根据标准中的定义,无效的 XML 实际上不是 XML。如果无法让生产者修复它,则必须在本地提取文件,例如将其读入字符串,然后进行搜索和替换。但如果它被正确转义,你的 XML 解析器应该为你处理所有的细节。
      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-07
        • 1970-01-01
        • 2011-07-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多