[英]XSLT: How do I match on the first occurrence of a given element?
<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
可以出現在文檔中的任何位置 。
要僅匹配文檔中第一次出現的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>
這個問題也可以通過一個鍵來解決,在其中您可以使用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
之類的函數(如果參數是文字或變量/參數) 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.