1

XML

<dsInventory>
  <Room>
    <RoomName>kantoor 1</RoomName>
    <RoomId>1376257</RoomId>
  </Room>
  <Room>
    <RoomName>Hal</RoomName>
    <RoomId>1376258</RoomId>
  </Room>
<Method>
    <RoomId>1376257</RoomId>
    <Name>test</Name>
  </Method>
<Method>
    <RoomId>1376258</RoomId>
    <Name>test</Name>
  </Method>
</dsInventory>

XSL

 <xsl:for-each select="/dsInventory/Room">
        <xsl:for-each select="/dsInventory/Method">
             <xsl:if test="RoomId=../RoomId">
             </xsl:if>
         </xsl:for-each>
    </xsl:for-each>

問題

roomid に基づいて、対応する部屋のメソッドを選択しようとしています。ただし、セレクター ../RoomId は機能しません。最初の for-each から RoomId の値を取得するにはどうすればよいですか? または、部屋の方法を選択する適切な方法は何ですか?

4

3 に答える 3

0

使用している XSLT のバージョンまたは期待される出力を指定していません。XSLT 1.0 が必要で、ドキュメントをコピーしたいが、リンクされたメソッド名をルームの下に追加し、メソッドをドロップすると仮定します。

この XSLT 1.0 スタイルシートは ...

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*" />

<xsl:template match="@*|node()">
 <xsl:copy>
  <xsl:apply-templates select="@*|node()"/>
 </xsl:copy>
</xsl:template>

<xsl:template match="Method"/>

<xsl:template match="Room">
 <xsl:copy>
  <xsl:apply-templates select="@*|node()"/>
  <xsl:apply-templates select="../Method[RoomId=current()/RoomId]/Name"/>
 </xsl:copy>
</xsl:template>

</xsl:stylesheet>

...サンプル入力ドキュメントに適用すると、...が生成されます

<dsInventory>
  <Room>
    <RoomName>kantoor 1</RoomName>
    <RoomId>1376257</RoomId>
    <Name>test</Name>
  </Room>
  <Room>
    <RoomName>Hal</RoomName>
    <RoomId>1376258</RoomId>
    <Name>test</Name>
  </Room>
</dsInventory>

説明

current() 関数を使用して、Room テンプレートのシーケンス コンストラクター (この場合は Room 要素) に相対的な現在のアイテムを指定します。述語では、current()/RoomId を select 式の Method ステップの RoomId と比較します。したがって、リンクされた名前は部屋の下にコピーされます。xsl:if なし、xsl:for-each なし、変数なし。すべては、current() 関数を使用して選択式で実現できます。

于 2012-07-15T14:55:41.730 に答える
0
<xsl:for-each select="/dsInventory/Room">
    <xsl:for-each select="/dsInventory/Method">
        <xsl:if test="RoomId=../RoomId"></xsl:if>
    </xsl:for-each>
</xsl:for-each>

この質問に答えた人々が指摘したように、あなたは a と a を比較しようとしていますが/dsInventory/Method/RoomId/dsInventory/RoomId後者は提供された XML ドキュメントには存在しません。

roomid に基づいて、対応する部屋のメソッドを選択しようとしています。

これを行う方法を示す完全な変換を次に示します。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="Room">
  <xsl:copy>
    <xsl:apply-templates/>
    <xsl:apply-templates mode="grab" 
         select="/*/Method[RoomId = current()/RoomId]"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="Method" mode="grab">
  <xsl:copy>
   <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>
 <xsl:template match="Method | Method/RoomId"/>
</xsl:stylesheet>

この変換が次の XML ドキュメント(メソッド名が変更された提供されたもの -- 互いに異なるもの) に適用される場合:

<dsInventory>
    <Room>
        <RoomName>kantoor 1</RoomName>
        <RoomId>1376257</RoomId>
    </Room>
    <Room>
        <RoomName>Hal</RoomName>
        <RoomId>1376258</RoomId>
    </Room>
    <Method>
        <RoomId>1376257</RoomId>
        <Name>test1</Name>
    </Method>
    <Method>
        <RoomId>1376258</RoomId>
        <Name>test2</Name>
    </Method>
</dsInventory>

必要な正しい結果が生成されます (メソッドがルームに追加されMethod、最上位要素の子が削除されます)。

<dsInventory>
   <Room>
      <RoomName>kantoor 1</RoomName>
      <RoomId>1376257</RoomId>
      <Method>
         <Name>test1</Name>
      </Method>
   </Room>
   <Room>
      <RoomName>Hal</RoomName>
      <RoomId>1376258</RoomId>
      <Method>
         <Name>test2</Name>
      </Method>
   </Room>
</dsInventory>

説明:

  1. アイデンティティ ルールは、実行対象として選択されたすべてのノードを「そのまま」コピーします。

  2. ID テンプレートをオーバーライドするテンプレートは、 に一致しRoomます。ここで、Room要素は「浅いコピーされ、テンプレートがその子に適用されます (これにより、それらのアイデンティティ テンプレートが選択され、それらは「そのまま」出力にコピーされます)。次に、子が同じ値を持つ任意Methodの にRoomIdテンプレートが適用されます。RoomId現在一致している ( current())要素の子としてRoom. 後で任意のMethod要素を削除したいので、ここでは必要な処理 (削除とは異なります) を"grab"モードで実行することを指定します.

  3. ID テンプレートをオーバーライドする 2 番目のテンプレートは、すべてのMethod要素を一致させ、本文を空にするだけで、すべての要素を削除します。

  4. Methodin モードに一致するテンプレートは、"grab"単純にそれを浅くコピーし、テンプレートをその子に適用します。その子のうち、Nameは ID テンプレートによってのみ照合され、「そのまま」コピーされます。子はRoomIdID テンプレートよりも具体的なテンプレートによって照合され、前者が実行用に選択されます。選択されたテンプレートには本文がなく、一致したものが出力から効果的に「削除」Method/RoomIdされます。

于 2012-07-15T15:10:41.253 に答える
0

ここでの問題はコンテキストです。ノードのコンテキストから実行されているため、if条件は失敗しておりMethod、XPath 式は上のノードを../RoomID探しています。そのようなノードはありません。RoomIDdsInventory

どのような出力が必要かは言いませんが、部屋を反復処理してそれぞれのメソッドを見つけたいという前提に基づいて、これを試してください: (また、for-each ループではなくテンプレートを使用することに注意してください。 XSLで)。

これを実行して、この XML Playgroundで出力を確認できます。

<!-- kick things off from the point of dsInventory -->
<xsl:template match="dsInventory">
    <ul><xsl:apply-templates select='Room' /></ul>
</xsl:template>

<!-- room nodes -->
<xsl:template match='Room'>
    <xsl:variable name='method' select='../Method[RoomId = current()/RoomId]' />
    <li>
        <xsl:value-of select='concat(RoomName," (",RoomId,")")' />:
        method = <xsl:value-of select='concat($method/Name," (",$method/RoomId,")")' />
    </li>
</xsl:template>
于 2012-07-15T14:39:10.303 に答える