【问题标题】:Escape xml characters within nodes of string xml in java在java中字符串xml的节点内转义xml字符
【发布时间】:2015-01-07 17:37:57
【问题描述】:

我有一串 XML 数据。我需要转义节点内的值,而不是节点本身。

例如:
<node1>R&R</node1>
应该逃到:
<node1>R&R</node1>
不应该逃到:
<node1>R&R</node1>

过去几天我一直在研究这个问题,但没有取得太大的成功。我不是 Java 专家,但以下是我尝试过但不起作用的方法:

  1. 将字符串 xml 解析为文档。不起作用,因为节点内的数据包含无效的 xml 数据。
  2. 转义所有字符。不起作用,因为接收此数据的程序不会接受这种格式的数据。
  3. 转义所有字符,然后解析为文档。引发各种错误。

任何帮助将不胜感激。

【问题讨论】:

  • “我有一串 XML 数据”——不,你没有。
  • 更正:“我有一串与 XML 非常相似的数据”

标签: java xml xml-parsing escaping


【解决方案1】:

您可以使用正则表达式匹配来查找尖括号之间的所有字符串,并遍历/处理每个字符串。在这个例子中,我使用了Apache Commons Lang 来进行 XML 转义。

public String sanitiseXml(String xml)
{
    // Match the pattern <something>text</something>
    Pattern xmlCleanerPattern = Pattern.compile("(<[^/<>]*>)([^<>]*)(</[^<>]*>)");

    StringBuilder xmlStringBuilder = new StringBuilder();

    Matcher matcher = xmlCleanerPattern.matcher(xml);
    int lastEnd = 0;
    while (matcher.find())
    {
        // Include any non-matching text between this result and the previous result
        if (matcher.start() > lastEnd) {
            xmlStringBuilder.append(xml.substring(lastEnd, matcher.start()));
        }
        lastEnd = matcher.end();

        // Sanitise the characters inside the tags and append the sanitised version
        String cleanText = StringEscapeUtils.escapeXml10(matcher.group(2));
        xmlStringBuilder.append(matcher.group(1)).append(cleanText).append(matcher.group(3));
    }
    // Include any leftover text after the last result
    xmlStringBuilder.append(xml.substring(lastEnd));

    return xmlStringBuilder.toString();
}

这会查找 text 的匹配项,捕获标签名称和包含的文本,清理包含的文本,然后将其重新组合在一起。

【讨论】:

  • 我选择了与此非常相似的东西。它似乎工作正常,但我有点担心几个小众案例。我正计划根据您的建议对我的代码进行一些更改。
  • 有一点需要注意;如果您的 XML 不包含子节点,则此建议非常有用。但是,如果您有这种形式的数据,则需要对其进行修改:&lt;ParentNode&gt; &lt;childNode1&gt;data&lt;/childNode1&gt; &lt;childNode2&gt;da&amp;&amp;ta&lt;/childNode2&gt; &lt;/ParentNode&gt; 这将仅返回子节点,而父节点将丢失。
  • 不,匹配之间的任何不匹配文本也将包含在结果中,因此子节点应该可以正常工作。它没有尝试修复的一件事是引用的属性字符串中的非法字符,例如
【解决方案2】:

问题在于&lt;node1&gt;R&amp;R&lt;/node1&gt; 不是 XML。

  • 使用 XML 解析器无济于事。 XML 解析器的目的就是过滤掉这类数据。

  • 您可以尝试使用 different parser 来解析“脏”HTML。

但我认为最好的解决方案是首先获得正确的 XML:

  • 通过使用 XML 库创建数据来修复 XML 源。 (并且永远不要使用字符串连接来创建 XML)

  • 如果为您提供了数据,请创建一个 XML-Schema 并坚持输入数据的有效性。

【讨论】:

  • 这行不通,因为我正在处理一组固定长度的数据。例如:我得到 100 个字节的数据,它恰好包含一个 & 符号。然后,它通过将这 100 个字节解析为一个期望正好为 100 个字节的 XML 模式的过程。如果我在解析之前转义 XML 字符,我现在通过模式发送 104 个字节,并且所有数据都被错误地转移。
【解决方案3】:

您展示的不是 XML。是 XPL。 XPL 的结构与 XML 类似,但允许在文本字段中使用 XML 的“特殊字符”。您可以使用 XPL 实用程序轻松地将 XPL 转换为 XML。 http://hll.nu

【讨论】:

    【解决方案4】:

    我使用了无名之声的答案,但正则表达式为:

    Pattern xmlCleanerPattern = Pattern.compile("(<[^<>]*>)(.*)(<\\/[^<>]*>)")
    

    我发现这可以更好地捕获节点本身内的所有值

    【讨论】:

      猜你喜欢
      • 2021-10-24
      • 2012-08-30
      • 2011-05-23
      • 2011-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-23
      • 1970-01-01
      相关资源
      最近更新 更多