0

以下の入力にはXSLTが必要です。この変換の目的は、特定のアイテムが削除または再作成されたかどうかを識別することです。

入力例は次のとおりです。 最初のシナリオ:

<root> 
    <nodeA id="a">
        <object id="1">
            <item1 id="xx" method="create">
                <attr>
                    <color>yellow</color>
                </attr>
            </item1>
        </object>
        <object id="1">
            <item1 id="xx" method="change">
                <any>blah</any>
                <attr>
                    <color>green</color>
                </attr>
            </item1>
            <item1 id="xx" method="delete" />                
        </object>  
        <object id="2">
            <item1 id="yy" method="create">
               <any>aaa</any>
            </item1>
        </object>
    </nodeA>            
</root>

出力:

<root> 
    <nodeA id="a">
        <object id="1">            
        </object>
        <object id="1">           
            <item1 id="xx" method="delete" />                
        </object>  
        <object id="2">
            <item1 id="yy" method="create">
               <any>aaa</any>
            </item1>
        </object>
    </nodeA>            
</root>

上記の最初のシナリオでは、item1が作成、変更、削除されたことがわかります。つまり、最終的には削除されます。そのため、を保持し<item1 id="xx" method="delete" />、もう一方を無視します。

2番目のシナリオ:

<root> 
    <nodeB id="a">
        <object id="2">
            <item2 id="xx" method="create">
                <attr>
                    <color>yellow</color>
                </attr>
            </item2>
        </object>
        <object id="2">
            <item2 id="xx" method="change">
                <attr>
                    <color>green</color>
                </attr>
            </item2>
            <item2 id="xx" method="delete" /> <!-- because deletion occurs here, we disregard any previous node up until this delete -->
            <item2 id="xx" method="create"> <!-- we keep this node and any node afterwards -->
                <attr>
                    <color>pink</color>
                </attr>
            </item2>
            <item2 id="xx" method="change">
                <any>blah</any>
                <attr>
                    <color>red</color>
                </attr>
            </item2>
        </object>  
        <object id="3">
            <item2 id="yy" method="create">
                <any>ccc</any>
            </item2>
        </object>
    </nodeB>            
</root>

出力:

<root> 
    <nodeB id="a">
        <object id="2">            
        </object>
        <object id="2">            
            <item2 id="xx" method="create"> 
                <attr>
                    <color>pink</color>
                </attr>
            </item2>
            <item2 id="xx" method="change">
                <any>blah</any>
                <attr>
                    <color>red</color>
                </attr>
            </item2>
        </object>  
        <object id="3">
            <item2 id="yy" method="create">
                <any>ccc</any>
            </item2>
        </object>
    </nodeB>            
</root>

2番目のシナリオでは、item2が作成および変更された後、削除されてから再作成および/または再変更されていることがわかります。そのため、削除するまではすべてのノードを無視し、その後はすべてのノードのみを保持します。

結論として:

  • 作成/変更/.../削除->削除になります

  • create / change /.../ delete / create2 / change2 / ...-> create2 / change2 / .. ..

どんな助けでも大歓迎です。ありがとう。

ジョン

4

1 に答える 1

2

XSLTでコーディングするルールは2つあると思います

  • 'delete'メソッドを持つアイテムがある場合、同じ@id(および親@id)に次のアイテムがない場合にのみ出力します。

  • 'delete'以外のメソッドを持つアイテムがある場合、同じ@id(および親@id)に対して後続の'delete'アイテムがない場合にのみ出力されます。

最初のルールはそのようにエンコードできます

<xsl:if test="not(following::*
   [not(.//*[@id!=''])]
   [@id=current()/@id]
   [../@id = current()/../@id]
   [generate-id(../..) = generate-id(current()/../..)])">

そして2番目のルールはそうです

 <xsl:if test="not(following::*
     [not(.//*[@id!=''])]
     [@method='delete']
     [@id=current()/@id]
     [../@id = current()/../@id]
     [generate-id(../..) = generate-id(current()/../..)])">

@id属性を持つ子要素を持たない要素を探すことによって、「item」ノード(つまり、item1またはitem2 )を識別していることに注意してください。また、どちらの場合も、これは現在のnodeA/B要素内でのみ発生すると想定しています。

これが完全なXSLTです

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

    <xsl:template match="*[not(.//*[@id!=''])][@method='delete']">
        <xsl:if test="not(following::*[not(.//*[@id!=''])][@id=current()/@id][../@id = current()/../@id][generate-id(../..) = generate-id(current()/../..)])">
            <xsl:call-template name="identity" />
        </xsl:if>
    </xsl:template>    

    <xsl:template match="*[not(.//*[@id!=''])][@method!='delete']">
        <xsl:if test="not(following::*[not(.//*[@id!=''])][@method='delete'][@id=current()/@id][../@id = current()/../@id][generate-id(../..) = generate-id(current()/../..)])">
            <xsl:call-template name="identity" />
        </xsl:if>
    </xsl:template>    

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

最初のXMLサンプルに適用すると、次のように出力されます。

<root>
    <nodeA id="a">
        <object id="1"/>
        <object id="1">
            <item1 id="xx" method="delete"/>
        </object>
        <object id="2">
            <item1 id="yy" method="create">
                <any>aaa</any>
            </item1>
        </object>
    </nodeA>
</root>

2番目のXMLサンプル(コメントなし)に適用すると、次のように出力されます。

<root>
    <nodeB id="a">
        <object id="2"/>
        <object id="2">
            <item2 id="xx" method="create">
                <attr>
                    <color>pink</color>
                </attr>
            </item2>
            <item2 id="xx" method="change">
                <any>blah</any>
                <attr>
                    <color>red</color>
                </attr>
            </item2>
        </object>
        <object id="3">
            <item2 id="yy" method="create">
                <any>ccc</any>
            </item2>
        </object>
    </nodeB>
</root>
于 2012-05-20T10:29:51.880 に答える