2

XML/XSL/Xpath は初めてで、一見単純な問題への回答を求めてこれらのボードを探しましたが、おそらく私は XSL に慣れていないため、これに対処する可能性のあるいくつかの回答を理解できません。

ドキュメントの別の場所に保存されているノード値の別のセットに一致するノードのセットを選択したいので、次のようにします。

<body>
    <partlist>
        <part>head</part>
        <part>spleen</part>
        <part>toe</part>
    </partlist>
    <parts>
        <head>this is a head</head>
        <spleen>this is a spleen</spleen>
        <toe>big toe</toe>
        <toe>big toe</toe>
    <parts>
</body>

そのため、すべての「パーツ」を数えたいとしますが、「パーツ」のノード名がわからない場合は、名前が別のセットの値と等しいノードのセットに XPath expr を一致させる必要があります。ノードの...

私は XSL に慣れていないため、解決策が非常に単純であると想像できますが、XSL から単純な解決策を期待するのは確実に間違った道であることを理解するには十分な経験があります。

私の手続きベースの無知では、これは私が試したことです:

<xsl:template match="/">
    <xsl:apply-templates select="partlist/part">
        <xsl:with-param name="parts" select="parts"/>
    </xsl:apply-templates>
</xsl:template>
<xsl:template match="part">
    <xsl:param name="parts"/>
    <xsl:value-of select="count($parts[.])"/>        
</xsl:template>

しかし、これは完全に間違っています。どんな助けでも大歓迎です。

編集:答えてくれてありがとう、しかし私は理解されていないと思います-私は完全に明確ではなかったので、私のせいです...必要なのは、一致するノードがあるかどうかを教えてくれる単一の結果です参照セットのノード値...クエリを変更すると思います。カウントのリストを出力しようとしていないため、セットをセットと照合して合計をカウントしようとしています...しかし、私にさせてくださいそのようなことが可能であれば、XSLで明確にしてください..これが上記の私のコードで、私の意図を明確にするためにわずかに変更されています:

<xsl:template match="/">
    <xsl:apply-templates select="partlist/part">
        <xsl:with-param name="parts" select="parts"/>
    </xsl:apply-templates>
</xsl:template>
<xsl:template match="part">
    <xsl:param name="parts"/>
    <xsl:if select="count($parts[.]) &gt; 0">1</xsl:if>        
</xsl:template>

上記を xml doc の例に適用すると、次のように出力されます。

1

これは理にかなっていますか?

編集:XSL 1.0に限定されていることも明記する必要があります

4

2 に答える 2

1

I. この XSLT 1.0 変換:

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

 <xsl:template match="part">
  <xsl:value-of select="."/>

  <xsl:value-of select=
  "concat(': ',
          count(/*/parts/*[name() = current()]),
          '&#xA;')"/>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

提供された XML ドキュメントに適用した場合:

<body>
    <partlist>
        <part>head</part>
        <part>spleen</part>
        <part>toe</part>
    </partlist>
    <parts>
        <head>this is a head</head>
        <spleen>this is a spleen</spleen>
        <toe>big toe</toe>
        <toe>big toe</toe>
    </parts>
</body>

必要な正しい結果が生成されます

head: 1
spleen: 1
toe: 2

説明:

テンプレートとcurrent()関数の適切な使用。


Ⅱ.単一の XPath 2.0 式の場合:

   /*/partlist
       /part
          /concat(.,
                  ': ', for $p in .
                         return count(/*/parts/*[name() eq $p]),
                  '&#xA;'
                 )

この Xpath 2.0 式が同じ XML ドキュメント (上記) に対して評価されると、必要な正しい結果が生成されます。

 head: 1
 spleen: 1
 toe: 2

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

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

 <xsl:template match="/">
  <xsl:sequence select=
  "/*/partlist
       /part
          /concat(.,
                  ': ', for $p in .
                         return count(/*/parts/*[name() eq $p]),
                  '&#xA;'
                 )
  "/>
 </xsl:template>
</xsl:stylesheet>

更新

OPは質問を変更しました。彼は次のことを望んでいるようです:

必要なのは、参照セットのノード値に一致するノードがあるかどうかを示す単一の結果です...

これも同様に簡単に実行できます。単一の XPath 式で取得できます

/*/parts/*[name() = /*/partlist/part]

この式は、要素の文字列値の 1 つであるものがあるtrue()場合に正確に評価されます。/*/parts/*name()/*/partlist/part

上記の式は、ブール値が期待される任意の場所で「そのまま」使用できます (任意の述語、or命令のtest属性の値など)。xsl:ifxsl:when

値 1 が必要な場合 (anf not true())、次を使用します。

number(/*/parts/*[name() = /*/partlist/part])

これにより、必要な結果 1 または 0 が得られます。定義により、次のようになります。

number(true()) = 1

number(false()) = 0
于 2012-07-29T21:07:14.200 に答える
1

この関数を使用しlocal-name()てノードの名前を取得し、それを特定の値と比較できます。

たとえば、スタイルシートを次のように変更できます。

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

  <xsl:template match="/">
    <xsl:apply-templates select="body/partlist/part"/>
  </xsl:template>

  <xsl:template match="part">
    <xsl:variable name="part" select="."/>
    <xsl:value-of select="count(/body/parts/*[local-name() = $part])"/>
  </xsl:template>

</xsl:stylesheet>

追加するために編集:

単一の値だけでなく、一連の値と比較することもできます。XPath 1.0 仕様のセクション 3.4から :

比較対象の 1 つのオブジェクトがノード セットであり、もう 1 つのオブジェクトが文字列である場合、文字列値で比較を実行した結果がノード セット内に存在する場合にのみ、比較は真になります。ノードの他の文字列は true です。

/body/partsにリストされている部分とローカル名が一致する要素の数を数えたい場合は、次の/body/partlist/partXPath 式を使用して実行できます。

count(/body/parts/*[local-name() = /body/partlist/part])

編集後に追加された質問からの最後の変換は、たとえば次のように書き直すことができます。

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

  <xsl:template match="body">
    <xsl:apply-templates select="partlist">
      <xsl:with-param name="parts" select="parts"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="partlist">
    <xsl:param name="parts"/>
    <xsl:if test="count($parts/*[local-name() = current()/part]) &gt; 0">1</xsl:if>        
  </xsl:template>

</xsl:stylesheet>
于 2012-07-29T20:48:47.650 に答える