2

このコードが最もクリーンではないことはわかっていますが、残念ながら適切にリファクタリングすることはできません。

position()問題は、2 回目の繰り返しで真の値が返されることを期待することです。しかし、position()それを使用すると、2回目の反復で期待されるように、決してtrueを返しません。

しかし、選択値をハードコーディングすると、期待される結果が返されます。次に例を示します。

<root>
  <MainProducts>
    <MainProduct>
      <Published>0</Published>
    </MainProduct>
    <MainProduct>
      <Published>1</Published>
    </MainProduct>
  </MainProducts>
  <SubProducts>
    <SubProduct>
      <IsDefault>1</IsDefault>
    </SubProduct>
    <SubProduct>
      <IsDefault>0</IsDefault>
    </SubProduct>
  </SubProducts>
</root>



XML コンテンツ:

<xsl:for-each select="/root/SubProducts/SubProduct">
  <script type="text/javascript">
    // Always returns false
    console.log("Dynamic position " + <xsl:value-of select="position()" /> + " IsDefault: " + ( <xsl:value-of select="/root/MainProducts/MainProduct[position()]/Published" /> == 1 ? "true" : "false" ));
  </script>
</xsl:for-each>

<script type="text/javascript">
  // Returns false, but expected to return true on second iteration.
  console.log("Hard coded position 1 IsDefault: " + ( <xsl:value-of select="/root/MainProducts/MainProduct[1]/Published" /> == 1 ? "true" : "false" ));

  // Returns true
  console.log("Hard coded position 2 IsDefault: " + ( <xsl:value-of select="/root/MainProducts/MainProduct[2]/Published" /> == 1 ? "true" : "false" ));
</script>



正確なコンソール出力は次のとおりです。

Dynamic position 1 IsDefault: false
Dynamic position 2 IsDefault: false
Hard coded position 1 IsDefault: false
Hard coded position 2 IsDefault: true

position()ノードを適切に選択していないために、ここで何が欠けていますか?

4

1 に答える 1

5
  <script type="text/javascript">
    // Always returns false
    console.log("Dynamic position " + 
   <xsl:value-of select="position()" /> + 
    " IsDefault: " + 
      ( <xsl:value-of select="/root/MainProducts/MainProduct[position()]/Published" /> 
        == 1 ? "true" : "false" ));
  </script>

上記のコードは)don't forget that is context-sensitive!MainProduct[position()]と同等です。MainProduct[true()]position()

したがって、実際に評価しているのは次のとおりです。

<xsl:value-of select="/root/MainProducts/MainProduct/Published" />

Publishedこれは常に、XPath 式によって選択された最初の要素の文字列値を出力します0

正しいコード:

<xsl:variable name="vPos" select="position()"/>

  <script type="text/javascript">
    // Always returns false
    console.log("Dynamic position " + 
   <xsl:value-of select="position()" /> + 
    " IsDefault: " + 
      ( <xsl:value-of select=
             "/root/MainProducts/MainProduct[position()=$vPos]/Published" /> 
        == 1 ? "true" : "false" ));
  </script>

完全な変換は次のとおりです。

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

 <xsl:template match="/">
   <xsl:for-each select="/*/SubProducts/SubProduct">
    <xsl:variable name="vPos" select="position()"/>

      <script type="text/javascript">
        console.log("Dynamic position " +
       <xsl:value-of select="position()" /> +
        " IsDefault: " +
          ( <xsl:value-of select=
             "/*/MainProducts/MainProduct
                         [position()=$vPos]/Published" />
            == 1 ? "true" : "false" ));
      </script>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

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

<root>
    <MainProducts>
        <MainProduct>
            <Published>0</Published>
        </MainProduct>
        <MainProduct>
            <Published>1</Published>
        </MainProduct>
    </MainProducts>
    <SubProducts>
        <SubProduct>
            <IsDefault>1</IsDefault>
        </SubProduct>
        <SubProduct>
            <IsDefault>0</IsDefault>
        </SubProduct>
    </SubProducts>
</root>

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

<script type="text/javascript">
        console.log("Dynamic position " +
       1 +
        " IsDefault: " +
          ( 0
            == 1 ? "true" : "false" ));
      </script>
<script type="text/javascript">
        console.log("Dynamic position " +
       2 +
        " IsDefault: " +
          ( 1
            == 1 ? "true" : "false" ));
      </script>
于 2013-02-21T04:11:34.003 に答える