使用XSLT转换XML并保留CDATA(在Ruby中)
我试图将一个包含如下内容的文档转换为另一个文档,使CDATA与第一个文档中的内容完全相同,但我还没有弄清楚如何使用XSLT保留CDATA 初始XML:使用XSLT转换XML并保留CDATA(在Ruby中),xml,xslt,parsing,nokogiri,cdata,Xml,Xslt,Parsing,Nokogiri,Cdata,我试图将一个包含如下内容的文档转换为另一个文档,使CDATA与第一个文档中的内容完全相同,但我还没有弄清楚如何使用XSLT保留CDATA 初始XML: <node> <subNode> <![CDATA[ HI THERE ]]> </subNode> <subNode> <![CDATA[ SOME TEXT ]]> </subNode> <
<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"><![CDATA[</text>
<value-of select="normalize-space(text())" disable-output-escaping="yes"/>
<text disable-output-escaping="yes">]]></text>
![CDATA[
]]
这将在CDATA中包装所有text()节点,这符合我的需要,并且它将在文本中保留html标记。如果CDATA节点与纯文本节点混合,则无法保留其精确顺序。通过在
xsl:output/@CDATA-section-elements
中列出特定元素的名称,您最多只能强制输出中该元素的所有内容为CDATA:
<xsl:output cdata-section-elements="text"/>
很抱歉为我自己的问题发布了一个答案,但我发现了一些有效的方法:
![CDATA[
]]
这将把所有text()节点包装在CDATA中,这符合我的需要,并将html标记保留在文本中。我在试图解决类似问题时发现了本文(使用XSL转换获取一个XML文件,并创建其中一些节点的部分/子集副本,作为第二个XML文件)。在我的例子中,第一个XML文件有一些元素,它们的值完全包装在CDATA块中,因为它们恰好是JSON,并且带有一些HTML格式标记 我发现,我可以使用
xsl:copy of
,而不是使用xsl:value of
,正如@Pavel Minaev所指出的,我可以通过在xsl:output声明中列出每个相关元素名称来保持原始CDATA的完整性。这可能是一种适用于OP的方法
要复制的XML(示例):
100
...
相关样式表行:
<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的例子中,我相信他会选择
//node/subNode
,然后在newDoc/data
中构建一个名为text
的元素。他的cdata节元素属性
将是简单的=“text”
,与Pavel的属性完全相同。在使用xslt之前,我应该使用ruby或者正则表达式对它们进行预处理吗,或者类似的东西?否则你会怎么做?cdata部分元素并没有很好地切割它,因为我使用了变量等。谢谢你的提示。如果你真的需要CDATA,那么你必须寻找XSLT以外的东西。也就是说,我很好奇你为什么需要它。XDM不区分文本和CDATA有一个很好的理由——任何正常的XML处理应用程序都不应该为它们提供不同的语义,因此CDATA和字符转义应该可以互换使用。我在Flash中使用这些数据,我听说CDATA/无CDATA存在很多问题。我还没有真正尝试过这样的方法:我想这是一种在输出中获取CDATA节点的方法(除了可以在输入text()
中获取]>
,在这种情况下,它并不能完全满足您的期望),但我不知道这将如何让您保留最初存在的CDATA节点,因为您仍然无法区分输入文本节点和输入CDATA节点。否则,我看不出这与cdata节元素有什么不同。。。
<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>