Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用XSLT转换XML并保留CDATA(在Ruby中)_Xml_Xslt_Parsing_Nokogiri_Cdata - Fatal编程技术网

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

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

我试图将一个包含如下内容的文档转换为另一个文档,使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[
]]

这将在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>