2012-04-02 22 views
2

XSLTには新機能が追加されましたが、ここでは多くのことを学んでいます。しかし、私は1つの問題に立ち往生しています。XSLTネストされた参照

私はXSLTを使用してデバイスインストールのレポートを作成しています。入力XMLは次のようになります。

<DeviceTypes> 
    <DeviceInfo Model="51473"> 
    <Channels> 
     <ChannelInfo ChannelId="1" IsImplemented="false" SampRateHardware="448" /> 
     <ChannelInfo ChannelId="2" IsImplemented="true" SampRateHardware="224" /> 
    </Channels> 
    </DeviceInfo> 
    <DeviceInfo Model="51474"> 
    <Channels> 
     <ChannelInfo ChannelId="1" IsImplemented="true" SampRateHardware="448" /> 
     <ChannelInfo ChannelId="2" IsImplemented="true" SampRateHardware="224" /> 
    </Channels> 
    </DeviceInfo> 
</DeviceTypes> 
<Installation> 
    <InstalledDevice Serial="597657" Model="51473"> 
    <Channels> 
     <InstalledChannel ChannelId="1" Name="foo" /> 
     <InstalledChannel ChannelId="2" Name="bar" /> 
    </Channels> 
    </InstalledDevice> 
</Installation> 

私は唯一の対応ChannelInfoがtrueに設定された「IsImplemented」を持っている場合InstallChannelノードを処理したいです。 "対応する"とは、同じChannelIdと同じモデルを親ノードの下に持つChannelInfoを探しているということです。同一のChannelIdを持つチャネルは、そのデバイスがどのデバイスに属しているかによってIsImplementedの値が異なる場合があります。

正常に検索するためにkey()関数を使用していますが、このネストされた参照は私を困惑させます。

おかげで、

このような何かが動作するはず

答えて

0

私はテンプレートを使用して読みやすく/拡張性のために作ることを信じている:キーはInstalledChannelのXPathでChannelInfoノードのためのモデルとChannelIdの両方を参照することができるように変数を使用して、その開始されますInstalledDeviceで、我々は我々のモデル変数のコンテキストを維持できるようにするため階層構造

<xsl:apply-templates select="//InstalledDevice"/> 

<xsl:template match="//InstalledDevice"> 
    <xsl:variable name="model"> 
     <xsl:value-of select="@Model"/> 
    </xsl:variable> 

    <xsl:for-each select="Channels/InstalledChannel"> 
     <xsl:variable name="channelId"> 
     <xsl:value-of select="@ChannelId"/> 
     </xsl:variable> 

     <xsl:if test="//DeviceInfo[@Model=$model]/Channels/ChannelInfo[@ChannelId=$channelId and @IsImplemented='true']"> 
     Processing Goes Here 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 

ダウンあなたの方法を動作し、私は、同じテンプレートにInstalledChannel処理を移動させ、ために - それぞれ追加しました。こうすることで、各InstalledChannelインスタンスを個別に処理して処理する必要があるかどうかを調べることができます。ここ

+0

ありがとうございます。私はあなたが近くだと思う。ここでもまた、異なるDeviceInfoの下に同じChannelIdを持つ複数のChannelInfoが存在し、必ずしもすべてが同じIsImplementedを持つとは限りません。これを説明するために例を更新します。 – mek363

+0

問題はありませんが、同じ一般的な概念がそのまま適用されます。ツリーを少し上げてからxpathを少し複雑にするだけです。 (私は私の答えを更新しました)。 – javram

+0

私はあなたの変数 "channelId"が最初のInstalledChannelを取得するという問題があると思いますが、複数の場合があります。私は私の例を単純にしているようにしていました。もう一度更新します。ありがとう。 – mek363

0

-mat。

/Installation/InstalledDevice/Channels/InstalledChannel/[count(/DeviceTypes/DeviceInfo/Channels/ChannelInfo[@ChannelId = @ChannelId and @IsImplemented = 'true') = 1] 
+0

ありがとうございました。私は、異なるDeviceInfoの下で同じChannelIdを持つ複数のChannelInfoが存在する可能性があり、必ずしもすべてが同じIsImplementedを持つとは限らないため、これはうまくいくとは思わない。 – mek363

1

は短く、単純な(無条件文、無変数なしxsl:for-each)溶液を使用してキーではない:この変換は、単一の上部にラップ設けXMLフラグメント(上に塗布する

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

<xsl:key name="kCI-ByIdImpl" match="ChannelInfo" 
    use="concat(@ChannelId, 
       '+', @IsImplemented, 
       '+', ../../@Model)"/> 

<xsl:template match="/*"> 
    <xsl:copy-of select= 
    "Installation/*/* 
     /InstalledChannel 
       [key('kCI-ByIdImpl', 
        concat(@ChannelId, '+true', 
          '+', ../../@Model) 
        ) 
       ]"/> 
</xsl:template> 
</xsl:stylesheet> 

整形式のXML文書を行うべき要素):

<t> 
    <DeviceTypes> 
     <DeviceInfo Model="51473"> 
      <Channels> 
       <ChannelInfo ChannelId="1" IsImplemented="false" SampRateHardware="448" /> 
       <ChannelInfo ChannelId="2" IsImplemented="true" SampRateHardware="224" /> 
      </Channels> 
     </DeviceInfo> 
     <DeviceInfo Model="51474"> 
      <Channels> 
       <ChannelInfo ChannelId="1" IsImplemented="true" SampRateHardware="448" /> 
       <ChannelInfo ChannelId="2" IsImplemented="true" SampRateHardware="224" /> 
      </Channels> 
     </DeviceInfo> 
    </DeviceTypes> 
    <Installation> 
     <InstalledDevice Serial="597657" Model="51473"> 
      <Channels> 
       <InstalledChannel ChannelId="1" Name="foo" /> 
       <InstalledChannel ChannelId="2" Name="bar" /> 
      </Channels> 
     </InstalledDevice> 
    </Installation> 
</t> 

のみ希望InstalledChannel要素が(この場合には、単に出力にコピー)処理される:

<InstalledChannel ChannelId="2" Name="bar"/> 

説明:複合キーの適切な使用。

関連する問題