使用XSLT检查XML节点名称是否包含字母

3

这不是唯一的关于此问题的问题,但我无法从其他解决方案中弄清楚我的代码为什么有错。这是为了一个作业,我已经大部分搞定了,但我无法理解为什么条件从未计算为true。如果我编写一个虚拟子句,例如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(包括根元素)。
同时,为什么当我调用<xsl:value-of select="name(node())" />时,我得到的是XSLT文件节点的名称(“xsl:stylesheet”),而不是正在被我的XSLT文档处理的当前节点的名称?
谢谢!
2个回答

4
我很惊讶你运行XSLT时没有出现错误,因为我使用Microsoft的XSLT处理时会出现错误“在谓词外部只允许使用'child'和'attribute'轴模式”,这是因为在XPath中,点是上下文节点的缩写。
我想知道你使用的XSLT处理是否将顶层文档节点与match="."(类似于match="/")匹配,这就解释了为什么你没有得到任何输出。
无论如何,在这里你真正需要的是<xsl:template match="*">,而不是<xsl:template match="." /> 但是,你真正应该做的是构建基于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中没有显式模板时,会使用这些内置模板。这些内置模板将输出文本节点的文本,并对其他节点继续处理其子节点(而不复制该节点)。因此,"/"的所有模板所做的就是内置模板本来就会做的事情。

0

你似乎缺少一些基本概念。

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

而且由于你正在要求当前节点的第一个子节点的名称,并且你得到的是xsl:stylesheet,这告诉我你正在将样式表作为输入 XML 执行该指令,并将当前节点作为根节点。

我预见到问题,如果文档元素不包含 'a',那么你没有做任何处理其余部分的文档。

也许如果你描述一下你的任务是什么,而不是展示给我们不起作用的代码,可能会有帮助... 但另一方面,如果有人给你答案,那么实际上你就没有得到真正的帮助。


作业要求我们只复制名称中包含字母 a 的元素。如果一个元素不包含 a,你还需要清除它的所有子元素。这就是为什么我使用 match='.',这样我就可以使用 <xsl:apply-templates select="child::node()" /> 来进一步深入一层,如果当前层满足条件。我现在遇到的问题是,如果有一点条件不满足,执行就会停止。这就是为什么我的输出总是为空的原因。它首先找到了 xml:stylesheet,然后跳过了其余部分。 - undefined
如果首先找到了xsl:stylesheet,那么你的调用就出错了。你正在用样式表作为输入数据来调用样式表。在你的问题中没有显示出输入数据是什么。如果确实有xml:stylesheet作为其文档元素,那么当输出为空时,满足“清除所有子项”的要求。顺便说一句,当在<xsl:apply-templates/>中省略select=时,它是select="child::node()"的缩写。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接