1

次のような xml で動作する汎用 XSLT 2.0 関数を作成したいと思います。

<?xml version="1.0"?>
<foo xmlns:my="http://meohmy.org" xmlns:yours="http://meohmy2.org">
    <yours:pet my:type="dog" my:color="red">Cindy</yours:pet>
    <yours:pet my:type="cat">Felix</yours:pet>
    <yours:pet my:type="cat" my:color="green">Pai Mei</yours:pet>
</foo> 

次のような関数シグネチャが与えられます。

my:doit('item',/foo/yours:/pet,@my:color)

(最初の引数はラベルで、2 番目は報告したいノードセットで、3 番目は 2 番目の引数のノードセット内のノードごとに出力したい値です。それがあるかどうかは関係ありません)。

次のようなデータを返します。

info=red;;green

問題の 3 番目の引数のない要素に対応する空のプレースホルダーが必要であり、順序が重要であることに注意してください。

スタイルシートでこれを何度も (さまざまな理由で何十回も) 行っているため、関数を使用するのが自然な方法のように思えました。これは私がこれまでに思いついたものです...

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:my="http://meohmy.org" 
    xmlns:yours="http://meohmy2.org">

   <xsl:template match="/">
       <xsl:value-of select="my:doit('item',/foo/yours:pet,@my:color)"/>
   </xsl:template>

   <xsl:function name="my:doit" as="xs:string?">
      <xsl:param name="item" as="xs:string"/>
      <xsl:param name="value"/>
      <xsl:param name="subvalue"/>
      <xsl:if test="$value">
        <xsl:value-of>
             <xsl:value-of select="$item"/>
             <xsl:text>=</xsl:text>
             <xsl:for-each select="$value">
                  <xsl:value-of select="current()/$subvalue"/>
              <xsl:if test="position() != last()">
                   <xsl:text>;</xsl:text>
              </xsl:if>
             </xsl:for-each>
        </xsl:value-of>
    </xsl:if>
  </xsl:function>
</xsl:stylesheet>

ただし、これを行うと、関数 doit() から次の値を取得します。

item=;;

<xsl:value-of select="current()/$subvalue"/>これは、スタイルシートで が正しくないことを示唆しています。私は近くにいます、私はそれを感じることができます;>何か提案はありますか?

ありがとう!

4

2 に答える 2

1

あなたの例では、XPath 式を 3 番目の引数として渡していると思いますが、そうではなく、その値を渡しています。

XPath 3.0 では、この問題に対する明確な解決策があります。関数を 3 番目の引数として渡すことができます。したがって、呼び出しは次のようになります

select="my:doit('item', /foo/yours:pet, function($e){$e/@my:color})"

そして実装は

      <xsl:function name="my:doit" as="xs:string?">
          <xsl:param name="item" as="xs:string"/>
          <xsl:param name="value" as="element()*/>
          <xsl:param name="subvalue" as="function(element()) as xs:string?"/>
          <xsl:if test="$value">
            <xsl:value-of>
                 <xsl:value-of select="$item"/>
                 <xsl:text>=</xsl:text>
                 <xsl:value-of select="$value ! $subvalue(.)" separator=";"/>
            </xsl:value-of>
        </xsl:if>
      </xsl:function>

XPath 3.0 を使用する立場にない場合 (上記は Saxon-PE 9.5 で機能します)、代わりに (a) XSLT 2.0 で高次関数をシミュレートする Dimitre Novatchev の FXSL ライブラリを使用するか、(b)関数を渡す代わりに、文字列の形式で XPath 式を渡し、xx:eval() 拡張関数を使用して式を動的に評価します。多くのプロセッサはそのような拡張機能を提供していますが、標準言語にはありません。

(注、XPath 3.0 では、A!B は「for $x in A return $x/B」と本質的に同じ意味です)

于 2013-06-26T08:23:30.027 に答える
1

このスタイルシートを試してください

    <?xml version="1.0"?>
    <xsl:stylesheet version="2.0" 
        xmlns:xs="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
        xmlns:my="http://meohmy.org" 
        xmlns:yours="http://meohmy2.org">

       <xsl:template match="/">
           <xsl:value-of select="my:doit('item',/foo/yours:pet,'my:color')"/>
       </xsl:template>

       <xsl:function name="my:doit" as="xs:string?">
          <xsl:param name="item" as="xs:string"/>
          <xsl:param name="value"/>
          <xsl:param name="subvalue"/>
          <xsl:if test="$value">
            <xsl:value-of>
                 <xsl:value-of select="$item"/>
                 <xsl:text>=</xsl:text>
                 <xsl:for-each select="$value">
                      <xsl:value-of select="current()/attribute()[name() = $subvalue]"/>
                  <xsl:if test="position() != last()">
                       <xsl:text>;</xsl:text>
                  </xsl:if>
                 </xsl:for-each>
            </xsl:value-of>
        </xsl:if>
      </xsl:function>
    </xsl:stylesheet>

それは私に結果を与えました

item=red;;green
于 2013-06-26T06:09:18.887 に答える