使用cdata转义XML,该cdata还具有转义的数据值和标记

本文关键字:cdata 转义 数据 XML 使用 | 更新日期: 2023-09-27 18:18:19

我正在从一个web服务接收xml数据,该服务将所有数据作为一个转义的xml字符串返回。但是,由于某种原因,XML的一部分被包含在cdata标记中。cdata中的转义xml通常也包含转义xml字符。例子:

<root>
  <importData>dat</importData>
  <Response>
   <![CDATA[&lt;SecondRoot&gt;
   &lt;Data&gt;123&lt;/Data&gt;
   &lt;DataEscapedCharacterIncluded&gt; 3 &gt; 1&lt;/DataEscapedCharacterIncluded&gt;
   &lt;/SecondRoot&gt;]]>
  &lt;/Response&gt;
&lt;/root&gt;

我需要用xsl将cdata部分内部和外部的xml转换为另一种xml格式,但是我很难弄清楚如何使用c#或xsl将其转换为可用的xml形式,因此我可以将xsl转换为不同的格式。我希望它看起来像这样:

  <root>
     <importData>dat</importData>
     <Response>
      <SecondRoot>
       <Data>123</Data>
       <DataEscapedCharacterIncluded> 3 &gt; 1</DataEscapedCharacterIncluded>
      </SecondRoot>
     </Response>
  <root>

使用cdata转义XML,该cdata还具有转义的数据值和标记

显示的数据可能没有正确转义。如果对其进行反转义,则可能产生格式不佳的XML。考虑这一行:

&lt;DataEscapedCharacterIncluded&gt; 3 &gt; 1&lt;/DataEscapedCharacterIncluded&gt;

如果你取消转义,它将变成这样:

<DataEscapedCharacterIncluded> 3 > 1</DataEscapedCharacterIncluded>

这仍然是有效的(大于不需要转义),但我假设您还会在那里的某个地方有&lt;,其中必须转义。如果它是双重转义的,应该没问题。

要转换它,你可以做几件事:

  • 使用XSLT 1.0或2.0,分两步对其进行转换,其中一步完成不转义,将disable-output-escaping设置为yes,另一个一个来做实际的转换。
  • 使用一个扩展函数,该函数接受一个字符串并返回一个节点集。
  • 在XSLT 3.0中,使用新的函数fn:parse-xmlfn:parse-xml-fragment,它可以将xml作为字符串作为输入。
  • 如果您的整个源被转义,就像它看起来的那样,将未转义的源馈送到XSLT处理器。这也会照顾到转义后的CDATA(但该部分仍将转义,见下文)。

从你的帖子中不完全清楚的是它是否被双重转义。例如,如果您的数据看起来像这样:

<elem><![CDATA[<root>bla</root>]]></elem>

被单独转义。如果它看起来像这样:

<elem><![CDATA[&lt;root&gt;bla&lt;/root&gt;]]></elem>

被双重转义。在后一种情况下,您需要在处理它之前执行一个额外的unescape循环。