使用XSLT转换XML并保留CDATA(在Ruby中)

时间:2009-10-01 05:42:19

标签: xml xslt parsing nokogiri cdata

我正在尝试将包含以下内容的文档转换为另一个文档,使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?

谢谢! 兰斯

使用ruby / 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>

这将包装CDATA中的所有text()节点,这些节点适用于我需要的内容,并且它将在文本中保留html标签。

3 个答案:

答案 0 :(得分:5)

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

<xsl:output cdata-section-elements="text"/>

答案 1 :(得分: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>

这将包装CDATA中的所有text()节点,这些节点适用于我需要的内容,并且它将在文本中保留html标签。

答案 2 :(得分:0)

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

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

要复制的XML(示例):

xsl:copy-of

相关的样式表行:

<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> 属性意味着在输出中,当转换运行时,从 复制的XML中的原始CDATA块将按原样传递到输出XML文件。 。看来您可以根据需要命名任意多个元素。

在OP的示例中,我相信他会在cdata-section-elements上进行选择,然后在//node/subNode内建立一个名为text的元素。就像帕维尔(Pavel)所言,他的newDoc/data就是cdata-section-elements attribute