使用XSLT将XML标记替换为文本节点

时间:2017-10-14 09:32:20

标签: xml xslt xslt-1.0

我已经多次在这里看过类似的问题,但我不确定它们是否适用于我的情况,或者我是否只是不了解这个过程。

我有一个XML文件,其中包含一系列规则:

<rules>
    <rule id="1">
        <block>
            [HTML content]
        </block>
        <block>
            [HTML content]
        </block>
        <block>
            [HTML content]
        </block>
    </rule>
    <rule id="2">
        <block>
            [HTML content]
        </block>
        <block>
            [HTML content]
        </block>
    </rule>
    [...]
</rules>

现在我的代码就像:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <xsl:template match="/rules/rule">
        [some output to create the header and title]
        <xsl:for-each select="block">
            <xsl:copy-of select="./node()" />
        </xsl:for-each>
        [some output to create the footer]
    </xsl:template>
</xsl:stylesheet>

要清楚,这不是整个文档,而是当用户点击规则以查看内容并且代码被简化很多时通过AJAX调用的部分,有一些必须要做的决定关于如何显示各种block元素的内部内容,但是现在这些部分对于我的问题是不必要的,只会使代码更难阅读。

在这种特殊情况下,XSLT似乎不太合适,因为我直接存储HTML内容,但这是一个更大的项目的一部分,数据更加原理图,这是我必须的唯一部分求助于这个解决方案。

但是,在rule标记内,有些表格使用规则的ID和第二个数字编号,例如1-1,1-2,......问题是,我有大约20个规则并计划以非线性方式扩展列表。现在我想在规则1和规则2之间添加规则,因此我必须更正以下所有表ID。这已经发生在过去,我确定将来会再次发生,所以我想避免这种无用的额外工作,并用<id />标记替换静态数字,例如Table <id />-12: [...]并将<id />替换为规则ID。我试图以这种方式修改代码:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <xsl:template match="/rules/rule">
        [some output to create the header and title]
        <xsl:for-each select="block">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*" />
            </xsl:copy>
        </xsl:for-each>
        [some output to create the footer]
    </xsl:template>
    <xsl:template match="id"><xsl:value-of select="ancestor::rule/@id" /></xsl:template>
</xsl:stylesheet>

替换有效,唯一的问题是<block>标签没有被移除,就像之前的代码一样,而其他每个标签都消失了。我只有一个没有任何HMTL标签的文本块。

我无法提出此解决方案,我将其从this one等问题中复制出来,但这是我第一次遇到<xsl:copy><xsl:apply-templates>标记,所以我不确定它们是如何工作的。此外,我发现的所有示例都与之前链接的示例类似,其中需要几乎完全相同的副本。我还必须在主输出周围添加许多额外的代码,并且我不确定它是如何与替换相互作用的。

修改:我也尝试了变体

            <xsl:apply-templates select="node()|@*">
                <xsl:copy-of select="./node()" />
            </xsl:apply-templates>

for-each周期内,但我获得了相同的结果:没有标签的文本,但替换有效。看起来apply-templates标记会删除所有标记,但我不知道如何保留它们。

1 个答案:

答案 0 :(得分:2)

查看找到的解决方案中的for-each循环:

<xsl:for-each select="block">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
</xsl:for-each>

在这个循环中:

  • <xsl:copy>输出开始标记,实际为<block>
  • <xsl:apply-templates .../> - “执行”源标记的内容。
  • </xsl:copy>输出结束标记,这次是</block>

由于您不想使用<block>标记,只需删除<xsl:copy></xsl:copy>

要防止其他代码消失,请将身份模板添加到您的 脚本。

原因是元素的内置模板:

  • 不会“复制”开始和结束标记,
  • 它只是将模板应用于他们的孩子,包括文本节点。

您必须覆盖此内容,包括身份模板