2

私の XML コード (パブと人を含む):

<document>
    <pubs>
        <pub id="pub1">
            <open>true</open>
        </pub>
        <pub id="pub2">
            <open>false</open>
        </pub>
    </pubs>
    <people>
        <person>
            <name>John</name>
            <pubId>pub1</pubId>
        </person>
        <person>
            <name>Paul</name>
            <pubId>pub2</pubId>
        </person>
    </people>
</document>

<person>from からへの参照<pub>( person/pubIdreferences ) を使用しますpub[@id]。パブ自体にはブール値があります<open>(パブが開いているか閉じているかを示します)。

count()XSLTを使って、パブに行ける人数を増やしたい。パブに行くには、パブの<open>値が である必要がありますtrue

私が完全にコーディングできない2つの可能な解決策:

  1. 人を反復処理し、数を追跡します。

    <xsl:for-each select="person">
        <xsl:variable name="pId" select="pubId" />
    
        <xsl:if test="root()/document/pubs/pub[@pubId=$pId]/open = 'true'" >
            <!-- any way to keep track of this number? -->
        </xsl:if>
    </xsl:for-each>
    
  2. count() 関数を直接使用します。

    <count>
        <xsl:value-of select="count(//person[root()/document/pubs/pub[@id = pubId]/open = 'true'])" />
    </count>
    

2 番目のオプションはより簡潔で正しいようですが、うまくいきません。

何か案は?

4

3 に答える 3

1

この XPath 1.0 ワンライナーを使用します

count(/*/people/person[pubId = /*/pubs/pub[open = 'true']/@id])

これは、属性の文字列値がそれと等しく、子の文字列値が stringである要素が存在するようなperson、少なくとも 1pubIdつの子を持つこのドキュメント内の要素の数を返します。pubidpubIdopen"true"

XSLT ベースの検証は次のとおりです。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:template match="/">
  <xsl:copy-of select=
      "count(/*/people/person[pubId = /*/pubs/pub[open = 'true']/@id])"/>
 </xsl:template>
</xsl:stylesheet>

この変換が提供された XML ドキュメントに適用されると、次のようになります。

<document>
    <pubs>
        <pub id="pub1">
            <open>true</open>
        </pub>
        <pub id="pub2">
            <open>false</open>
        </pub>
    </pubs>
    <people>
        <person>
            <name>John</name>
            <pubId>pub1</pubId>
        </person>
        <person>
            <name>Paul</name>
            <pubId>pub2</pubId>
        </person>
    </people>
</document>

Xpath 式が評価され、この評価の結果が出力にコピーされます。

1
于 2012-08-31T12:33:56.203 に答える
0

はい、2 番目の方法が正しい方法です。基本的に結合を行っています。Tim C が指摘しているように、キーは XSLT で結合を行うのに役立つことがよくあります。

あなたの試みの理由

count(//person[root()/document/pubs/pub[@id = pubId]/open = 'true'])

'pubId' のコンテキストが間違っているため、機能しません。範囲変数を使用して XPath 2.0 でこれを解決できます。

count(for $p in //person return (if (/document/pubs/pub[@id = $p/pubId]/open = 'true') then $p else ()))

ただし、キーを使用する方が簡単で高速です。

于 2012-08-31T12:17:33.983 に答える
0

キーを使用してパブを検索してみてください

<xsl:key name="pubs" match="pub" use="@id" />

これにより、次のようにカウントを簡素化できます

<xsl:value-of select="count(//person[key('pubs', pubId)[open='true']])"/>

したがって、次の XSLT の場合

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
   <xsl:key name="pubs" match="pub" use="@id" />
   <xsl:template match="/">
      <count>
         <xsl:value-of select="count(//person[key('pubs', pubId)[open='true']])"/>
      </count>
   </xsl:template>
</xsl:stylesheet>

以下が出力されます

<count>1</count>

XSLT では、変数は不変であり、一度設定すると変更できないことに注意してください。したがって、変数を設定してインクリメントしようとする最初のアプローチは有効ではありません。

于 2012-08-31T08:33:57.357 に答える