7

我正在尝试将具有以下内容的文档转换为另一个文档,使 CDATA 与第一个文档中的内容完全相同,但我还没有弄清楚如何使用 XSLT 保留 CDATA。

初始 XML:

<node>
    <subNode>
        <![CDATA[ HI THERE ]]>
    </subNode>
    <subNode>
        <![CDATA[ SOME TEXT ]]>
    </subNode>
</node>

最终的 XML:

<newDoc>
    <data>
        <text>
            <![CDATA[ HI THERE ]]>
        </text>
        <text>
            <![CDATA[ SOME TEXT ]]>
        </text>
    </data>
</newDoc>

我尝试过这样的事情,但没有运气,一切都变得混乱:

<xsl:element name="subNode">
    <xsl:value-of select="." disable-output-escaping="yes"/>
</xsl:element>

任何想法如何保存 CDATA?

谢谢!槊

使用红宝石/nokogiri

更新:这是可行的。

<text disable-output-escaping="yes">&lt;![CDATA[</text>
<value-of select="normalize-space(text())" disable-output-escaping="yes"/>
<text disable-output-escaping="yes">]]&gt;</text>

这会将所有 text() 节点包装在 CDATA 中,这可以满足我的需要,并且它将在文本中保留 html 标签。

4

3 回答 3

5

如果 CDATA 节点与纯文本节点混合,则无法保留它们的精确序列。充其量,您可以强制输出中特定元素的所有内容为 CDATA,方法是在以下位置列出该元素名称xsl:output/@cdata-section-elements

<xsl:output cdata-section-elements="text"/>
于 2009-10-01T06:36:05.423 回答
3

很抱歉发布我自己问题的答案,但我发现了一些有用的东西:


<text disable-output-escaping="yes">&lt;![CDATA[</text>
<value-of select="normalize-space(text())" disable-output-escaping="yes"/>
<text disable-output-escaping="yes">]]&gt;</text>

这会将所有 text() 节点包装在 CDATA 中,这可以满足我的需要,并且它将在文本中保留 html 标签。

于 2009-10-05T08:28:33.077 回答
0

我在尝试解决类似问题时发现了这篇文章(使用 XSL 转换获取一个 XML 文件并创建其中一些节点的部分/子集副本,作为第二个 XML 文件)。在我的例子中,第一个 XML 文件有一些元素的值完全包含在 CDATA 块中,因为它们恰好是 JSON 并且它们带有一些 HTML 格式标记。

我发现xsl:value-of,我可以使用xsl:copy-of,而不是使用 ,正如@Pavel Minaev 指出的那样,我可以通过在 xsl:output 声明中列出每个相关元素名称来保持原始 CDATA 的完整性。这可能是一种适用于 OP 的方法。

要复制的 XML(示例):

<text_item>
  <id>100</id>
  <stem_text><![CDATA[(any string of text, including HTML)]]></stem_text>
  <answerOptions><![CDATA[{"choices":[{"label":"Atmospheric O<sub>2</sub>",
   "value":"A"},{"label":"Released CO<sub>2</sub>",
   "value":"B"}]}]]></answerOptions>
 ...
</text_item>

相关样式表行:

<xsl:output method="xml" indent="yes" cdata-section-elements="stem_text answerOptions" />
...
<xsl:apply-templates select="//text_item" >
...
<xsl:template match="text_item">
    <xsl:element name="text_item" >
        <xsl:copy-of select="node()"  />
    </xsl:element>
</xsl:template>

cdata-section-elements属性意味着,在输出中,其中复制的 XML 中的原始 CDATA 块将在转换运行时按原样传递到输出 XML 文件。看来您可以根据需要命名任意数量的元素。

在 OP 的示例中,我相信他会选择 on//node/subNode然后text在内部构建一个名为 的元素newDoc/data。他cdata-section-elements attribute会很简单="text",就像帕维尔所说的那样。

于 2018-08-30T22:58:17.427 回答