簡體   English   中英

XSLT:如何在給定元素首次出現時進行匹配?

[英]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-namename (或如果需要的名稱空間和名稱)來實現相同的功能,僅因為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM