2

次のような xml の複数のインスタンスがあります。

<refbody>
<ul>
    <li><uicontrol>FOO</uicontrol>BAR</li>
</ul>
<p>Values: 000 - 999</p>
<ul>
    <li><uicontrol>FOO</uicontrol>BAR</li>
    <li><uicontrol>FOO</uicontrol>BAR</li>
    <li><uicontrol>FOO</uicontrol>BAR</li>
    <li><uicontrol>FOO</uicontrol>BAR</li>
</ul>
<p>Values:</p>
<p>lorem ipsum</p>
<p>lorem ipsum</p>
<p>lorem ipsum</p>
</refbody>

私が実現したいのは、すべての<ul>要素を 1 つの .xmlに統合すること<dl>です。

それぞれ<li>が child を作成する必要があります<dlentry>

それぞれが、その の子である に<uicontrol>なる必要があります。<dt><dlentry>

の残りのテキストは、の子でもある 要素に<li>配置する必要があります。<dd><dlentry>

私のスタイル シート (以下に提供) は、すでにこれを実現しています。問題が発生しているのは最後の要件です。

に関連付けられて<p>いる の内部に配置する必要があります。 <dlentry>preceding-sibling::li[1]

したがって、望ましい結果は次のようになります。

<refbody>
<dl>
    <dlentry>
        <dt>FOO</dt>
        <dd>BAR
            <p>Values: 000 - 999</p>
        </dd>
    </dlentry>
    <dlentry>
        <dt>FOO</dt>
        <dd>BAR</dd>
    </dlentry>
    <dlentry>
        <dt>FOO</dt>
        <dd>BAR</dd>
    </dlentry>
    <dlentry>
        <dt>FOO</dt>
        <dd>BAR</dd>
    </dlentry>
    <dlentry>
        <dt>FOO</dt>
        <dd>BAR
            <p>Values:</p>
            <p>lorem ipsum</p>
            <p>lorem ipsum</p>
            <p>lorem ipsum</p>
        </dd>
    </dlentry>
</dl>
</refbody>

これを行うにはキーを使用する必要があると思いますが、正しく機能させることができません。誰かが私が間違っていることを教えてくれたら本当にありがたいです。

ここに私のスタイルシートがあります:

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

<xsl:key name="kValues" match="p" 
    use="generate-id[preceding::li[1]]"/>

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

<xsl:template match="ul[ancestor::refbody][1]">
    <dl>
        <xsl:for-each select="child::li|following::li">
            <xsl:variable name="vValues">
                <xsl:value-of select="key('kValues',generate-id())"/>
            </xsl:variable>
            <dlentry>
                <dt>
                    <xsl:value-of select="child::uicontrol"/>
                </dt>
                <dd>
                     <xsl:value-of select="text()"/>
                    <xsl:if test="$vValues">
                        <xsl:copy-of select="$vValues" />
                    </xsl:if>
                </dd>
            </dlentry>
        </xsl:for-each>
    </dl>
</xsl:template>

</xsl:stylesheet>
4

2 に答える 2

1

次のスタイルシートは、キーを使用せずに目的の出力を生成します。

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

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

    <xsl:template match="refbody">
        <xsl:copy>
            <dl>
                <xsl:apply-templates select="ul" />
            </dl>
        </xsl:copy>        
    </xsl:template>

    <xsl:template match="ul">
        <xsl:apply-templates select="*"/>
    </xsl:template>

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

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

    <xsl:template match="li/text()">
        <dd>
            <xsl:copy/>
            <xsl:apply-templates 
                 select="parent::li
                                 [not(following-sibling::li)]
                                 /parent::ul
                                 /following-sibling::p
                                 [
                                  count(preceding-sibling::ul) 
                                  = count(current()/../../preceding-sibling::ul)
                                    +1
                                 ]"/>
        </dd>
    </xsl:template>

</xsl:stylesheet>
于 2012-07-26T00:39:03.293 に答える
1

I. この変換(キーを使用した私のソリューション):

<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:key name="kFollowing"
      match="node()[self::p or self::text() and preceding-sibling::ul]"
      use="generate-id(preceding::li[1])"/>

     <xsl:template match="/*[ul]">
         <refbody>
             <dl>
               <xsl:apply-templates/>
             </dl>
         </refbody>
     </xsl:template>

     <xsl:template match="li">
         <dlentry>
           <xsl:apply-templates/>
         </dlentry>
     </xsl:template>

     <xsl:template match="li/text()">
         <dd>
           <xsl:value-of select="normalize-space()"/>
         </dd>
     </xsl:template>

     <xsl:template match="li[last()]/text()">
         <dd>
           <xsl:value-of select="."/>
           <xsl:copy-of select="key('kFollowing', generate-id(..))"/>
         </dd>
     </xsl:template>

     <xsl:template match="uicontrol">
         <dt>
           <xsl:apply-templates/>
         </dt>
     </xsl:template>
     <xsl:template match="p/text()"/>
</xsl:stylesheet>

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

<refbody>
    <ul>
        <li>
            <uicontrol>FOO</uicontrol>BAR
        </li>
    </ul>
    <p>Values: 000 - 999</p>
    <ul>
        <li>
            <uicontrol>FOO</uicontrol>BAR
        </li>
        <li>
            <uicontrol>FOO</uicontrol>BAR
        </li>
        <li>
            <uicontrol>FOO</uicontrol>BAR
        </li>
        <li>
            <uicontrol>FOO</uicontrol>BAR
        </li>
    </ul>
    <p>Values:</p>
    <p>lorem ipsum</p>
    <p>lorem ipsum</p>
    <p>lorem ipsum</p>
</refbody>

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

<refbody>
   <dl>
      <dlentry>
         <dt>FOO</dt>
         <dd>BAR
        <p>Values: 000 - 999</p>
         </dd>
      </dlentry>
      <dlentry>
         <dt>FOO</dt>
         <dd>BAR</dd>
      </dlentry>
      <dlentry>
         <dt>FOO</dt>
         <dd>BAR</dd>
      </dlentry>
      <dlentry>
         <dt>FOO</dt>
         <dd>BAR</dd>
      </dlentry>
      <dlentry>
         <dt>FOO</dt>
         <dd>BAR
        <p>Values:</p>
            <p>lorem ipsum</p>
            <p>lorem ipsum</p>
            <p>lorem ipsum</p>
         </dd>
      </dlentry>
   </dl>
</refbody>

Ⅱ.見つかったすべての間違いを修正した後の解決策:

<xsl:stylesheet
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 
    <xsl:key name="kValues" match="p"
        use="generate-id(preceding::li[1])"/>

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

    <xsl:template match="ul[ancestor::refbody][1]">
        <dl>
            <xsl:for-each select="child::li|following::li">
                <xsl:variable name="vValues" select="key('kValues',generate-id())"/>
                <dlentry>
                    <dt>
                        <xsl:value-of select="child::uicontrol"/>
                    </dt>
                    <dd>
                         <xsl:value-of select="text()[normalize-space()]"/>
                         <xsl:copy-of select="$vValues" />
                    </dd>
                </dlentry>
            </xsl:for-each>
        </dl>
    </xsl:template>
    
    <xsl:template match="p|ul|text()"/>
</xsl:stylesheet>

この修正された変換が同じ XML ドキュメント (上記) に適用されると、正確に必要な正しい結果が生成されます


III. 私が見つけた間違いの分析

  1. これは、目で確認する必要があるエラーです。

...

<xsl:key name="kValues" match="p"             
         use="generate-id[preceding::li[1]]"/> 

...

ここで、任意の要素は、先行する を持つpその子の文字列値によってインデックス付けされます。generate-idli

generate-idただし、 XML ドキュメントで指定された要素はありません。

本当に意図したのは、generate-id()関数を使用することでした。(関数呼び出しは、関数名の後に、通常の丸括弧とで囲まれた実際の引数値のシーケンスが続きます)。丸括弧を角括弧に置き換えると、式のセマンティクスが根本的に変わり、関数呼び出しが (相対) ロケーション ステップに変わります。

.2. これ

        <xsl:variable name="vValues">                               
          <xsl:value-of select="key('kValues',generate-id())"/>                           
        </xsl:variable>

(非常に)悪い習慣であるだけでなく、現在のケースのようにエラーの原因となることがよくあります。要素のノードセットではなく、ツリー (ドキュメント ノード) を作成しています。ツリーには常に少なくとも 1 つのノード (ドキュメント ノード) とそのブール値があるため、常に true です。

上記の構文は絶対に使用しないでください。

正しい変数宣言は次のとおりです。

            <xsl:variable name="vValues" select="key('kValues',generate-id())"/>

.3. アイデンティティ テンプレートによる不要なulp、およびtext()ノー​​ドのコピーを防止するテンプレート ルールはなく、これらは元の変換の結果に表示されます。

于 2012-07-26T02:40:08.240 に答える