Xml 无法处理cdata中的元素

Xml 无法处理cdata中的元素,xml,xslt,xslt-1.0,Xml,Xslt,Xslt 1.0,我正在尝试编辑CDATA中的链接: <paragraph> <![CDATA[ <strong><a href="http://example.com/2014/12/08/article-title">Article Title</a></strong>Article Excerpt. ]]> </paragraph> 文章节选。 ]]> 目标是将段落更改为,同时在链接

我正在尝试编辑CDATA中的链接:

 <paragraph>
    <![CDATA[
        <strong><a href="http://example.com/2014/12/08/article-title">Article Title</a></strong>Article Excerpt.
    ]]>
 </paragraph>

文章节选。
]]>
目标是将段落更改为
,同时在链接中添加其他标记。例如,所需的输出可以是:(并非所有的
都有链接,有些只包含文本)


文章节选。

我尝试了下面的代码,但没有成功

<xsl:template match="paragraph">
    <xsl:copy-of select="@*"/>
    <xsl:text disable-output-escaping="yes"><![CDATA[<p>]]></xsl:text>
    <xsl:value-of select="." disable-output-escaping="yes"/>
    <xsl:text disable-output-escaping="yes"><![CDATA[</p>]]></xsl:text>
</xsl:template>

<xsl:template match="text()[contains(.,'&lt;a href=&#34;') and contains(.,'&#34;>')]">

    <xsl:variable name="link" select="substring-before(substring-after(., '&lt;a href=&#34;'), '&#34;>')"/>

    <xsl:text disable-output-escaping="yes"><![CDATA[<a href="]]></xsl:text>
    <xsl:value-of disable-output-escaping="yes" select="$link"/>
    <xsl:text disable-output-escaping="yes"><![CDATA[&tracking_id=12345" ]]></xsl:text>
    <xsl:value-of select="$link_style"/>
    <xsl:text disable-output-escaping="yes"><![CDATA[>]]></xsl:text>
    <xsl:apply-templates select="child::node()"/>
    <xsl:text disable-output-escaping="yes"><![CDATA[</a>]]></xsl:text>

</xsl:template>

]]>
]]>
]]>
]]>

就XML处理器而言,
段落
节点中的CDATA不包含链接、标签或除单个文本节点以外的任何内容。它只是一个字符串,所以如果您真的想更改它,您必须求助于一些棘手的字符串操作

您遇到的第一个问题是,在匹配“段落”的模板中,您没有执行任何
xsl:apply templates
,因此永远不会调用可以匹配
段落下的文本节点的第二个模板

因此,第一个模板应该如下所示

<xsl:template match="paragraph">
    <p>
        <xsl:apply-templates />
    </p>
</xsl:template>
<xsl:template match="text()[contains(.,'&lt;a href=&#34;') and contains(.,'&#34;>')]">
    <xsl:variable name="firstbit" select="substring-before(., '&lt;a href=&#34;')"/>
    <xsl:variable name="link" select="substring-before(substring-after(., '&lt;a href=&#34;'), '&#34;>')"/>
    <xsl:variable name="lastbit" select="substring-after(substring-after(., '&lt;a href=&#34;'), '&#34;>')"/>

    <xsl:value-of disable-output-escaping="yes" select="$firstbit"/>
    <xsl:text disable-output-escaping="yes"><![CDATA[<a href="]]></xsl:text>
    <xsl:value-of disable-output-escaping="yes" select="$link"/>
    <xsl:text disable-output-escaping="yes"><![CDATA[?tracking_id=12345" ]]></xsl:text>
    <xsl:value-of select="$link_style"/>
    <xsl:text disable-output-escaping="yes"><![CDATA[>]]></xsl:text>
    <xsl:value-of disable-output-escaping="yes" select="$lastbit"/>
</xsl:template>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="paragraph">
        <p>
            <xsl:value-of disable-output-escaping="yes" select="." />
        </p>
    </xsl:template>
</xsl:stylesheet>
然后输出以下内容:

<p>
    <strong><a href="http://example.com/2014/12/08/article-title">Article Title</a></strong>Article Excerpt.
</p>
<p>
     <strong><a href="http://example.com/2014/12/08/article-title?tracking_id=12345" style="color:#067ab4;">Article Title</a></strong>Article Excerpt.
</p>

文章节选。


因此,如果您可以更改输入XML以消除CDATA,那么它将变得非常简单……

CDATA中没有任何元素—这就是它的用途!假设将SQL中的一行读入xml文件,其中一个字段包含HTML及其所有&wtf;实体、未终止的
标记和其他无效XML。你把它放在CData区域以防止XML试图解析它。嗨,蒂姆,非常感谢!我试试你的第一个解决办法。问题是我无法控制订阅源-我无法删除CDATA,因此必须找到令人讨厌的方法来处理它:(刚刚将您的解决方案应用到我的脚本中,效果非常好,非常感谢Tim!
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="a">
        <a href="{@href}?tracking_id=12345" style="color:#067ab4;">
            <xsl:apply-templates />
        </a>
    </xsl:template>
</xsl:stylesheet>
<p>
     <strong><a href="http://example.com/2014/12/08/article-title?tracking_id=12345" style="color:#067ab4;">Article Title</a></strong>Article Excerpt.
</p>