如何解决XML中的符号(&;)转换问题?

如何解决XML中的符号(&;)转换问题?,xml,Xml,我使用XMLDocument创建XML文件,但当XML节点获取“&”作为数据时,它将转换为“符号(&)amp;”,但我需要实际值,即“&”,有人能告诉我如何实现它吗 结果:单个&在XML文档中是非法的(在CDATA部分之外;请参阅@rsp的答案),因此这是不可能的。如果节点数据中存在逐字符号,则必须将其编码为& 但这也没有问题,因为任何XML读取器都将解码&作为文本。如果确实需要在XML表示中使用未替换的符号,则可以在字符数据周围使用节,但代价是开始和]>结束。我曾经遇到过这样的情况

我使用XMLDocument创建XML文件,但当XML节点获取“&”作为数据时,它将转换为“符号(&)amp;”,但我需要实际值,即“&”,有人能告诉我如何实现它吗


结果:

单个
&
在XML文档中是非法的(在CDATA部分之外;请参阅@rsp的答案),因此这是不可能的。如果节点数据中存在逐字符号,则必须将其编码为
&


但这也没有问题,因为任何XML读取器都将解码
&作为文本。

如果确实需要在XML表示中使用未替换的符号,则可以在字符数据周围使用节,但代价是
开始和
]>
结束。

我曾经遇到过这样的情况,我想在XML中保留原始的符号。尽管您的解析器可能与我的不同(我使用MarkLogic),但以下内容仍然适用于您使用任何XML解析器的情况:

与符号和字符有关的问题

    The ampersand character can be tricky to construct in an XQuery string, as it is an escape character to the XQuery parser. The ways to construct the ampersand character in XQuery are:

    Use the XML entity syntax (for example, &).
    Use a CDATA element (<![CDATA[element content here]]>), which tells the XQuery parser to read the content as character data.
    Use the repair option on xdmp:document-load, xdmp:document-get, or xdmp:unquote.
    https://help.marklogic.com/knowledgebase/article/View/55/0/xquery-ampersand-in-string
在XQuery字符串中构造符号和字符可能比较困难,因为它是XQuery解析器的转义字符。在XQuery中构造符号和字符的方法有:
使用XML实体语法(例如,&;)。
使用CDATA元素(),它告诉XQuery解析器将内容作为字符数据读取。
在xdmp:document load、xdmp:document get或xdmp:unquote上使用修复选项。
https://help.marklogic.com/knowledgebase/article/View/55/0/xquery-ampersand-in-string
显然,上面列出的第一个选择,即逃避安培生,并不是我们想要走的方向。我们想要的是原始的符号,而不是转义的实体。
第二个选项一开始似乎是个好主意,我使用CDATA元素玩了很长时间。CDATA允许“字符数据”,其中的所有内容都被视为字符数据,而不是真正的XML。在研究了一些示例之后,我发现您可能会使CDATA返回符号AND,但CDATA元素非常不友好。例如,创建动态CDATA元素几乎是不可能的,您不能简单地将XML结构包装到CDATA中。CDATA应该包含静态的预定义字符。如果有一种有效的使用CDATA的方法,我就找不到了。 Xdmp:quote和Xdmp:unquote实现了我们所需要的技巧,尽管不是以我们期望的方式。例如:

let $xml := <rootNode title="test"><firstLevel type="crazy"><secondLevel reason="testing">D&amp;C</secondLevel><secondLevel owner="clint">D&amp;C</secondLevel></firstLevel></rootNode>
return xdmp:quote($xml//secondLevel[1])
(: Returns <secondLevel reason="testing">D&amp;C</secondLevel> :)
let$xml:=D&;CD&;C
返回xdmp:quote($xml//secondLevel[1])
(:返回D&C:)
但是

let$xml:=D&;CD&;C
返回xdmp:quote($xml//secondLevel[1]/node())
(:返回D&C-一个未替换的符号!)
第二个示例给出了未替换的符号,但这仅仅是因为我们试图引用的对象是文本,而不是元素。在第一个示例中,如果我们尝试引用元素,它将返回XML的文本版本,但带有D&C转义的符号。因此,为了让xdmp:quote给我们一个带符号AND的字符串,带符号AND的对象必须是独立文本。
从这里开始,我们可能会有几个不同的方向,而我的想法肯定不是最优雅、最有效的。但我决定创建一个递归函数,将所有XML解析为文本,并允许对符号使用纯文本的xdmp:quote

declare function local:stringify($xml)
{
  if (xdmp:node-kind($xml) eq "text") then
    xdmp:quote($xml, <options xmlns="xdmp:quote">
                  <method>text</method>
                </options>)
  else if (xdmp:node-kind($xml) eq "element") then
      fn:string-join(
        (fn:concat("<", fn:local-name($xml)),
        for $attr in $xml/@*
          return fn:concat(' ', fn:local-name($attr), '="', $attr, '"'),
        ">",
        for $node in $xml/node()
          return local:stringify($node),
        fn:concat("</", fn:local-name($xml), ">")
      ), "")
  else ()
};

let $xml := <rootNode title="test"><firstLevel type="crazy"><secondLevel reason="testing">D&amp;C</secondLevel><secondLevel owner="clint">D&amp;C</secondLevel></firstLevel></rootNode>


return local:stringify($xml)
(: Returns <rootNode title="test"><firstLevel type="crazy"><secondLevel reason="testing">D&C</secondLevel><secondLevel owner="clint">D&C</secondLevel></firstLevel></rootNode> :)
declare函数local:stringify($xml)
{
如果(xdmp:node-kind($xml)eq“text”),那么
xdmp:quote($xml,
文本
)
else if(xdmp:node-kind($xml)eq“element”)则
fn:字符串连接(
(fn:concat(“,
对于$xml/node()中的$node
返回本地:stringify($node),
fn:concat(“”)
), "")
else()
};
让$xml:=D&;CD&;C
返回本地:stringify($xml)
(:返回D&CD&C:)

因此,虽然这个解决方案不允许在我们的应用程序中传递的XML中存在符号,但它确实允许传递这个被视为文本的打包XML。

我想可以使用下面的行。 像
“完全修复”
这样的选项将仅将
&
作为
&


让$InputXML:=xdmp:unquote($inputSearchDetails,”,(“format xml”,“repair full”)

可能重复@AndersR.Bystrup:我不认为这是他问的问题。他问的是如何避免漏掉符号。如果“任何xml阅读器都会解码”不是真的,那就没用了。
declare function local:stringify($xml)
{
  if (xdmp:node-kind($xml) eq "text") then
    xdmp:quote($xml, <options xmlns="xdmp:quote">
                  <method>text</method>
                </options>)
  else if (xdmp:node-kind($xml) eq "element") then
      fn:string-join(
        (fn:concat("<", fn:local-name($xml)),
        for $attr in $xml/@*
          return fn:concat(' ', fn:local-name($attr), '="', $attr, '"'),
        ">",
        for $node in $xml/node()
          return local:stringify($node),
        fn:concat("</", fn:local-name($xml), ">")
      ), "")
  else ()
};

let $xml := <rootNode title="test"><firstLevel type="crazy"><secondLevel reason="testing">D&amp;C</secondLevel><secondLevel owner="clint">D&amp;C</secondLevel></firstLevel></rootNode>


return local:stringify($xml)
(: Returns <rootNode title="test"><firstLevel type="crazy"><secondLevel reason="testing">D&C</secondLevel><secondLevel owner="clint">D&C</secondLevel></firstLevel></rootNode> :)