<xsl:template match="//foo[1]">
匹配多个元素(每个<foo>
没有以前的<foo>
兄弟姐妹)
<xsl:template match="(//foo)[1]">
是一个错误。
如何匹配文档中第一次出现的元素?
以下是输入文档的示例:
<test>
<foo>1</foo>
<another>
<foo>2</foo>
</another>
<more>
<bar>3</bar>
<foo>4</foo>
</more>
<something>
<foo>5</foo>
<bar>6</bar>
<foo>7</foo>
</something>
<final>
<hum>8</hum>
<foo>9</foo>
<foo>10</foo>
</final>
</test>
我的目的是将foo
与文字1
和没有其他相匹配。假设foo
可以在文档中任何地方出现。
答案 0 :(得分:5)
要仅匹配文档中第一次出现的foo
,您必须检查前面没有foo
个元素,并且没有foo
个祖先:
<xsl:template match="foo[not(preceding::foo or ancestor::foo)]">
请考虑以下示例输入XML:
<r>
<a/>
<foo>
<b/>
<foo/>
</foo>
<foo>
<foo/>
</foo>
<c/>
</r>
此XSLT,
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="foo[not(preceding::foo or ancestor::foo)]">
<FirstFoo>
<xsl:apply-templates/>
</FirstFoo>
</xsl:template>
<xsl:template match="foo">
<LaterFoo>
<xsl:apply-templates/>
</LaterFoo>
</xsl:template>
</xsl:stylesheet>
将输出此XML,
<?xml version="1.0" encoding="UTF-8"?>
<r>
<a/>
<FirstFoo>
<b/>
<LaterFoo/>
</FirstFoo>
<LaterFoo>
<LaterFoo/>
</LaterFoo>
<c/>
</r>
但如果您只检查前一个轴,则输出此XML:
<?xml version="1.0" encoding="UTF-8"?>
<r>
<a/>
<FirstFoo>
<b/>
<FirstFoo/>
</FirstFoo>
<LaterFoo>
<LaterFoo/>
</LaterFoo>
<c/>
</r>
答案 1 :(得分:0)
这个问题也可以通过一个键来解决,然后你可以使用XSLT 2.0识别foo
元素组中的第一个项目,这看起来像
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:key name="foo-group" match="foo" use="node-name(.)"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="foo[. is key('foo-group', node-name(.))[1]]">
<foo id="first-foo">
<xsl:apply-templates/>
</foo>
</xsl:template>
</xsl:transform>
在线http://xsltransform.net/gWEamLb。
使用XSLT 1.0,您可以使用local-name
或name
(或者如果需要的命名空间和名称)来实现相同的效果,只有在is
运算符不存在时才需要使用generate-id
标识第一项:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="foo-group" match="foo" use="local-name()"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="foo[generate-id() = generate-id(key('foo-group', local-name())[1])]">
<foo id="first-foo">
<xsl:apply-templates/>
</foo>
</xsl:template>
</xsl:transform>
在http://xsltransform.net/ejivdH9在线。
最后使用XSLT 3.0,我们可以将其写为
<xsl:stylesheet
version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:key name="foo-group" match="foo" use="node-name(.)"/>
<xsl:param name="foo-name" as="xs:QName" select="xs:QName('foo')"/>
<xsl:template match="key('foo-group', $foo-name)[1]">
<foo id="first-foo">
<xsl:apply-templates/>
</foo>
</xsl:template>
</xsl:stylesheet>
不需要<xsl:param name="foo-name" as="xs:QName" select="xs:QName('foo')"/>
并使用<xsl:template match="key('foo-group', xs:QName('foo'))[1]">
会更好,但即使是更强大的XSLT 3.0匹配模式也只允许我们使用像key
这样的函数是文字或变量/参数。