首页 > 解决方案 > 除非已经在 J​​avascript 中编码,否则对 XML 实体进行编码

问题描述

我有一种情况,我正在为 SOAP 请求生成 xml,并从第 3 方接收进入该 xml 的数据。此代码在服务器上运行,无法访问 DOM 中的函数。有时数据会包含已编码的 xml 实体,有时则不会。

例如有时我会收到这个: Billy & Joe's Garage

其他时候我会收到这个: Billy & Joe's Garage

我知道有处理第一个示例的解决方案,例如在这篇文章中找到的示例:如何在 javascript 中转义 xml 实体?

但是,如果我将这些解决方案应用于第二个示例,我将得到如下信息:

function escapeXml(unsafe) {
    return unsafe.replace(/[<>&'"]/g, function (c) {
        switch (c) {
            case '<': return '&lt;';
            case '>': return '&gt;';
            case '&': return '&amp;';
            case '\'': return '&apos;';
            case '"': return '&quot;';
        }
    });
}

escapeXml("Billy &amp; Joe&apos;s Garage")
// Returns "Billy &amp;amp; Joe&amp;apos;s Garage"

因此,对于第二个示例,所需的输出将与输入相同。

标签: javascriptxml

解决方案


当然,真正的解决办法是拒绝损坏的 XML 并将其退回给供应商。同时...

使用否定前瞻断言,您可以排除&后面出现的任何事件amp;quot;等等。

&(?!(amp|apos|lt|gt|quot);)

会这样做。

将此与您问题中的正则表达式结合起来,您应该能够绕过那些已经是已识别实体的一部分的&符号,同时替换那些不是:

const re = /&(?!(amp|apos|lt|gt|quot);)|[<>'"]/g

function escapeXml(unsafe) {
  return unsafe.replace(re, function(c) {
    switch (c) {
      case '<':
        return '&lt;';
      case '>':
        return '&gt;';
      case '&':
        return '&amp;';
      case '\'':
        return '&apos;';
      case '"':
        return '&quot;';
    }
  });
}
console.log(escapeXml("'Billy &amp; Joe&apos;s Garage & something else'"))


推荐阅读