避免在 SQL XML 属性中编码符号

Avoid encoding of ampersand in SQL XML attribute

Image 我有一种货币 table,包含例如这条记录:
- ID = 1
-代码=欧元
- 符号 = €
重要注意事项:
我们数据库中的输入已经 属性 HTML 编码!

现在,当我使用这个 SQL 语句时:

SELECT '@id'        = Currency.Id
    , '@code'       = Currency.Code
    , '@symbol'     = Currency.Symbol
FROM Currency
FOR XML PATH('currency')
    , ROOT('list')
    , TYPE
;

...不幸的是,结果如下 XML :

<list><currency id="1" code="EUR" symbol="&amp;euro;" /></list>

请注意,欧元符号已被重新编码,使其无效。

我怎样才能避免这种情况?如何获得以下 XML 输出:

<list><currency id="1" code="EUR" symbol="&euro;" /></list>

不幸得到的结果是重新编码无效是完全正确的- 但不是你所期望的。你传入 &euro; 这是一个字符串。在 XML 中,它被转义为 &amp;euro; 并将重新编码为 &euro;.

您必须停止将 XML 视为一种形式化的字符串。这是一个技术问题。 XML 将隐式处理此问题。

有两种方法:

  • 按照字符串方式将 XML 转换为 NVARCHAR,执行您可能需要的任何字符串操作(例如 REPLACE(myXML,'&amp;euro;','&euro;') 并转换回 XML 或

  • (我更喜欢这个!)将 € 作为实际符号提交,让 XML 引擎进行编码。

编辑

还有一件事:SQL 服务器不知道 &euro; 实体。尝试 &#8364;&#x20AC;:

SELECT '€' AS [@EuroSign]               --works
      ,'&euro;' AS [@NamedEscapedEuro]  --will be encoded
      ,'&#8364;' AS [@EscapedEuro]      --will be encoded
FOR XML PATH('TestEuro'),ROOT('root')

SELECT --CAST('<x>'+'€'+'</x>' AS XML).value('/x[1]','nvarchar(10)') AS [@EuroSign]              --not allowed!!!
       --CAST('<x>'+'&euro;'+'</x>' AS XML).value('/x[1]','nvarchar(10)') AS [@NamedEscapedEuro] --not allowed, exists, but not known in SQL Server!
       CAST('<x>'+'&#8364;'+'</x>' AS XML).value('/x[1]','nvarchar(10)') AS [@EscapedEuro]       --works
FOR XML PATH('TestEuro'),ROOT('root')