【问题标题】:Check if XML node name contains a letter using XSLT使用 XSLT 检查 XML 节点名称是否包含字母
【发布时间】:2013-08-11 21:36:45
【问题描述】:

这不是唯一的问题,但我无法从其他解决方案中找出我的代码错误的原因。这是一个作业,我已经弄清楚了大部分,但我不明白为什么条件永远不会评估为真。如果我编造了一个虚拟子句,例如 contains('a', 'a') 甚至 1=1,那么我可以看到正确的输出(但是显然没有被条件过滤)。

另外,如果我只是尝试使用<xsl:value-of select="name(.)" /> 输出当前元素的名称,则不会输出任何内容。显然,有些东西我没有到达这里,但它正在躲避我。有什么线索吗?

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" indent="yes" encoding="ISO-8859-1"/>

    <xsl:template match="/">
        <xsl:apply-templates select="node()" />
    </xsl:template>

    <xsl:template match=".">
        <xsl:if test="contains(name(.),'a')">
            <xsl:copy>
                <xsl:copy-of select="@*"/>
                <xsl:apply-templates select="child::node()" />
            </xsl:copy>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

在这种情况下,XML 模式根本不重要。我知道有些元素包含字母 a(包括根元素)。

另外,为什么当我调用&lt;xsl:value-of select="name(node())" /&gt; 时,我得到了 XSLT 文件节点的名称(“xsl:stylesheet”),而不是我的 XSLT 文档正在处理的文件中当前节点的名称?

谢谢!

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    我很惊讶您在运行 XSLT 时没有收到错误,因为当我使用 Mircosoft 的 XSLT 处理尝试它时,我收到错误 “只有 'child' 和 'attribute' 轴允许在外面的模式中谓词。”。这是因为在 XPath 中,点是上下文节点的缩写。

    我想知道您使用的 XSLT 处理是否将顶级文档节点与 match="." 匹配(类似于执行 match="/"),这可以解释为什么您没有得到任何输出。

    无论如何,这里确实需要&lt;xsl:template match="*"&gt;,而不是&lt;xsl:template match="." /&gt;

    但您真正应该做的是建立在 XSLT Identity Transform 的基础上,这是 XSLT 中的基本设计模式。它本身会复制输入 XML 中的所有现有节点,但您可以根据需要添加额外的模板匹配。

    在您的情况下,您说您只想复制名称中包含“a”的元素。好吧,反过来想,在这种情况下,你“不想”复制名称中没有“a”的元素。因此,您需要添加到身份转换的只是这个模板

    <xsl:template match="*[not(contains(name(), 'a'))]" />
    

    顺便说一句,您在这里并不需要“/”的初始模板

    <xsl:template match="/">
        <xsl:apply-templates select="node()" />
    </xsl:template>
    

    XSLT 有内置模板的概念,当 XSLT 中没有显式模板时使用。这些内置模板将为文本节点输出文本,而对于其他节点,它将继续处理子节点(不复制节点)。所以,“/”的所有模板所做的就是内置模板所做的。

    【讨论】:

      【解决方案2】:

      您似乎遗漏了一些基本概念。

      你有match='.',如果你想匹配你需要match='*'的所有元素。

      并且由于您询问当前节点的第一个子节点的名称,并且您得到xsl:stylesheet,这告诉我您正在执行该指令,其中样式表作为输入 XML,当前节点为根节点。

      而且我预见到如果文档元素不包含“a”,您将无法处理文档的其余部分。

      如果您描述您的任务是什么,而不是向我们展示什么不起作用,也许会有所帮助......但是,如果有人给您答案,那么您根本不会得到帮助,真的.

      【讨论】:

      • 作业要求我们只复制名称中包含字母 a 的元素。如果一个元素不包含 a,您还需要清除它的所有子元素。这就是我使用match='.' 的原因,如果当前级别满足条件,我可以使用&lt;xsl:apply-templates select="child::node()" /&gt; 更深一层。我现在遇到的问题是,如果在某一时刻不满足条件,则执行停止。这就是为什么我的输出总是空的。它先找到 xml:stylesheet 然后跳过其余部分。
      • 如果它首先找到xsl:stylesheet,那么你的调用就搞砸了。您正在使用样式表作为输入数据来调用样式表。您没有在问题中显示您的输入数据是什么。如果确实有 xml:stylesheet 作为其文档元素,那么当您有一个空输出时,您“清除其所有子项”的要求就得到了满足。顺便说一句,当&lt;xsl:apply-templates/&gt; 中省略了select= 时,select="child::node()" 的缩写。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-29
      • 2011-06-09
      • 2011-08-03
      • 2015-01-04
      • 1970-01-01
      • 2018-04-23
      相关资源
      最近更新 更多