Java: 转义 XML 文本内容而不是整个文本

Java: Escape XML text content instead of entire text

我想发送下面的 XML 请求。应转义文本内容,但不转义标签。

我试过使用下面的转义逻辑。
String str = escapeXml11(req);

但是,我的整个请求都被转义了。所以,它不再有效 XML.

我的原字符串:

String req =
"<request>\r\n" 
  + " <Products>\r\n" 
    + " <Product>\r\n" 
      + " <ProductName>H < M</ProductName>\r\n" 
      + " <quantity>1</quantity>\r\n" 
      + " <totalProductCost>17.03</totalProductCost>\r\n" 
    + " </Product>\r\n" 
  + " </Products>\r\n" 
+ "</request>"; 

转义后:

&lt;request&gt;
    &lt;ProductName&gt;H &lt; M&lt;/ProductName&gt;
    &lt;quantity&gt;1&lt;/quantity&gt;
    &lt;totalProductCost&gt;17.03&lt;/totalProductCost&gt;
&lt;/request&gt

预期结果:

<request>
    <ProductName>H &lt; M</ProductName>
    <quantity>1</quantity>
    <totalProductCost>17.03</totalProductCost>
</request>

如何只转义文本内容?

所以这个问题的根源是第3方提供给你的"XML"格式不正确

<request>
  <Products>
    <Product>
      <ProductName>H < M</ProductName>
      <quantity>1</quantity>
      <totalProductCost>17.03</totalProductCost>
    </Product>
  </Products> 
</request>

要更正此问题,您需要将 "H < M" 转换为 "H &lt; M"。人类很容易做到这一点,如果人类必须做很多这样的事情,模精度就会出现问题。但是自动化很难。

显然,简单地调用转义方法是行不通的。如果不解析 XML,转义方法无法确定需要转义的内容。 (像 escapeXml11 这样的方法只有在需要转义整个字符串时才有效。)

普通的 XML 解析器会看到 "< M" 尝试将其视为元素标记的开始。然后它会看到下一个 "<" ... 和错误。要进一步进行,它必须回溯到 "< M" 并将 "<" 视为已转义 .

我知道有一个 HTML / XML 解析器 (JSoup) 可以处理错位的 "<" 字符。但是,如果我理解正确,它会以错误的方式处理您的用例。与其将 "< M" 视为数据,不如将其转换为开始标记:

<request>
  <Products>
    <Product>
      <ProductName>H <M></ProductName>
      <quantity>1</quantity>
      <totalProductCost>17.03</totalProductCost>
    </Product>
  </Products> 
</request>

剩下两个选择:

  • 您可以尝试使用一些模式匹配来检测和修复问题。例如,如果您知道格式错误的数据在 <ProductName>...</ProductName> 元素中,那么您可以使用正则表达式搜索这些元素,检查并(如有必要)更正内容,然后替换它。

  • 您可以使用上下文相关的词法分析器为您的 XML 编写自定义解析器。当解析器看到 <ProductName> 时,它会将词法分析器切换到另一种模式,将“<”视为数据 ,除非 它是 [=24= 的开始].


但是在你去写一堆自定义代码来处理这个无效的时间和费用之前XML:

  • 向创建它的第 3 方投诉。他们不应该像那样排放垃圾。他们的软件或数据收集/清理存在缺陷。他们应该修复它。

  • 确保支付软件开发和维护费用的人知道这一点。例如,如果您签约编写一些处理 XML 的软件,这不是 XML。如果客户没有警告您您的软件需要处理格式错误的 XML,那是需求变更,可能(应该)是合同的 变体 .

另请参阅@Michael Kay 的评论。

这是我在到处寻找解决方案后发现的:

获取 Jsoup 库:

<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.12.1</version>
</dependency>

然后:


Document doc = Jsoup.parse(new ByteArrayInputStream(YOUR_XML_STRING_HERE.getBytes("UTF-8")), "UTF-8", "", Parser.xmlParser())
doc.outputSettings().charset("UTF-8")
doc.outputSettings().escapeMode(Entities.EscapeMode.base)

println doc.toString()

希望这对某人有所帮助