0

入力ファイル:

<workorders>
    <workorder>
        <renew id="a">
            <nodeA id="N1">
                <fruit id="1" action="aaa">

                    <orange id="x" action="aa">
                        <attributes>
                            <color>Yellow</color>
                            <ada>xxx</ada>
                        </attributes>
                    </orange>

                    <orange id="y" action="change">
                        <attributes>
                            <color>Red</color>
                            <year>2012</year>
                        </attributes>
                    </orange>
                    <orange id="x" action="aa">
                        <attributes>
                            <color>Pink</color>
                            <ada>xxx</ada>
                        </attributes>
                    </orange>
                    <orange id="y" action="change">
                        <attributes>
                            <color>Blue</color>
                            <condition>good</condition>
                        </attributes>
                    </orange>
                </fruit>
            </nodeA>
        </renew>
    </workorder>
</workorders>

私の出力:

<workorders>
    <workorder>
        <renew id="a">
            <nodeA id="N1">
                <fruit id="1" action="aaa">
                    <orange id="x" action="aa">
                        <attributes>
                            <color>Pink</color>
                            <ada>xxx</ada>
                        </attributes>
                    </orange>
                    <orange id="y" action="change">
                        <attributes>
                            <color>Blue</color>
                            <year>2012</year>
                            <condition>good</condition>
                        </attributes>
                    </orange>
                </fruit>
            </nodeA>
        </renew>
    </workorder>
</workorders>

期待される出力:

<workorders>
    <workorder>
        <renew id="a">
            <nodeA id="N1">
                <fruit id="1" action="aaa">
                    <orange id="x" action="aa">
                        <attributes>
                            <color>Yellow</color>
                            <ada>xxx</ada>
                        </attributes>
                    </orange>

                    <orange id="x" action="aa">
                        <attributes>
                            <color>Pink</color>
                            <ada>xxx</ada>
                        </attributes>
                    </orange>

                    <orange id="y" action="change">
                        <attributes>
                            <color>Blue</color>
                            <year>2012</year>
                            <condition>good</condition>
                        </attributes>
                    </orange>
                </fruit>
            </nodeA>
        </renew>
    </workorder>
</workorders>

XSLファイル:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:a="http://project.com">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:key name="entity" match="/workorders/*/*/*/*/*" use="concat(parent::*/@id, '_', @id, '_', @action)"/>

    <xsl:function name="a:is-primary" as="xs:boolean">
        <xsl:param name="ctx"/>
        <!-- need to establish "focus"(context) for the key() function to work -->
        <xsl:for-each select="$ctx">
            <xsl:sequence select="generate-id($ctx) = generate-id(key('entity', concat($ctx/parent::*/@id, '_', $ctx/@id, '_', $ctx/@action))[1])"/>
        </xsl:for-each>
    </xsl:function> 

    <xsl:function name="a:preceded-by" as="xs:boolean">
        <xsl:param name="ctx"/>
        <xsl:param name="action"/>
        <xsl:value-of select="count($ctx/preceding::*[a:matches($ctx, ., $action)]) > 0"/>
    </xsl:function>

    <xsl:function name="a:followed-by" as="xs:boolean">
        <xsl:param name="ctx"/>
        <xsl:param name="action"/>
        <xsl:value-of select="count($ctx/following::*[a:matches($ctx, ., $action)]) > 0"/>
    </xsl:function>

    <xsl:function name="a:matches" as="xs:boolean">
        <xsl:param name="src"/>
        <xsl:param name="target"/>
        <xsl:param name="action"/>

        <xsl:value-of select="
                     ($src/local-name() = $target/local-name()) and
                      ($src/parent::*/@id = $target/parent::*/@id) and 
                      ($src/@id = $target/@id) and 
                      (if ($action = 'same') 
                          then false()
                          else if ($action = 'any')
                              then ($target/@action = $src/@action)
                              else ($target/@action = $action))"/>  
    </xsl:function>

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

    <xsl:template match="/*/*/*/*/*/*[a:is-primary(.)]" priority="1">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="attributes" mode="consolidate-most-recent"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="attributes" mode="consolidate-most-recent">
        <xsl:copy>
            <xsl:for-each-group 
                        select="/workorders/*/*/*/*/*[a:matches(current()/parent::*, ., 'any')]/attributes/*" 
                        group-by="local-name()">
                <!-- take the last in the document order -->
                <xsl:apply-templates select="current-group()[last()]"/>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="/*/*/*/*/*/*[not(a:is-primary(.))]"/>    
   </xsl:stylesheet>

組み合わせのあるノードに対してのみ変換が機能するようにするには、xslファイルに何を追加する必要がありますか?action="change"現在、他のすべてのアクションの組み合わせをグループ化しています。

ありがとう。

4

1 に答える 1

1

予想される出力が実際にはすべてそのまま保持されると仮定する@action != 'change'と (つまり、それぞれの出現がattributes/*入力ドキュメント内の as を統合またはマージせずに出力することを意味します)、次の 2 つの小さな変更を加えるだけで済みます。

1) を最初の「キャプチャ」テンプレートに追加@action = 'change'します。

<xsl:template match="/*/*/*/*/*/*[action = 'change' and a:is-primary(.)]">

2)「サイレント非プライマリ」テンプレートについても同じことを行います。

<xsl:template match="/*/*/*/*/*/*[@action = 'change' and not(a:is-primary(.))]"/>

これにより、他のすべてのノードが ID 変換テンプレートを通過するようになります。入力ドキュメントに対してこれら 2 つの変更を加えて変換を実行すると、以下が生成されます。

<workorders>
   <workorder>
      <renew id="a">
         <nodeA id="N1">
            <fruit id="1" action="aaa">
               <orange id="x" action="aa">
                  <attributes>
                     <color>Yellow</color>
                     <ada>xxx</ada>
                  </attributes>
               </orange>
               <orange id="y" action="change">
                  <attributes>
                     <color>Blue</color>
                     <year>2012</year>
                     <condition>good</condition>
                  </attributes>
               </orange>
               <orange id="x" action="aa">
                  <attributes>
                     <color>Pink</color>
                     <ada>xxx</ada>
                  </attributes>
               </orange>
            </fruit>
         </nodeA>
      </renew>
   </workorder>
</workorders>

psノードを並べ替えて表示したい場合@action(予想される出力が示唆するように)、次のテンプレートをミックスに追加する必要があります。

<xsl:template match="/*/*/*/*/*">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="*">
            <xsl:sort select="@action"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

ppsa:matches()関数の書き方に少し戸惑います。論理式の最後の部分で次のようにします。

(if ($action = 'any') 
    then true()
    else if ($action = 'same')
        then ($target/@action = $src/@action)
        else ($target/@action = $action))

@action要求された場合は属性を気にせずany、要求された場合は2つを比較sameし、そうでない場合は特定の値が提供されたと仮定して、その値と比較します。same次に、テンプレートの値を使用して呼び出します。

<xsl:for-each-group 
    select="/workorders/*/*/*/*/*[a:matches(current()/parent::*, ., 'same')]/attributes/*" 
    group-by="local-name()">
于 2012-05-28T01:23:45.643 に答える