0

特定のメソッドが含まれている xml ファイル内のいくつかのノードを削除する必要があります。たとえば、ここに入力があります。

<root> 
<node id="a">
    <section id="a_1">
        <item id="0">
            <attribute>
                <color>Red</color>
            </attribute>
        </item>
    </section>

    <section id="a_2">
        <item id="0">
            <attribute>
                <color>Red</color>
            </attribute>
        </item>
    </section>            
</node>

<node id="b">
    <section id="b_1">         
        <user id="b_1b" method="pause">
            <attribute>a</attribute>
        </user>      
        <user id="b_1b" method="run">
            <attribute>a</attribute>
        </user>             
        <user id="b_1a" method="run">
            <attribute>
                <name>John</name>
            </attribute>
        </user>

        <user id="b_1a" method="pause">
            <attribute>a</attribute>
        </user>
    </section>

    <section id="b_1" method="create">   

        <user id="b_1b" method="stop">
            <attribute>a</attribute>
        </user>            
        <user id="b_1a" method="stop">
            <attribute>a</attribute>
        </user>

        <user id="b_1b" method="run">
            <attribute>a</attribute>
        </user>
        <user id="b_1b" method="pause">
            <attribute>a</attribute>
        </user>
    </section>

    <section id="b_2">                
        <user id="b_1a" method="run">
            <attribute>
                <name>John</name>
            </attribute>
        </user>
    </section>
</node>

この方法を使用する場合:

<xsl:transform version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:my="http://localhost"
  exclude-result-prefixes="my">

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

  <xsl:template match=" user[not(@method eq 'stop' )][not(. is my:last(.))]
  | user[    @method eq 'stop' ][not(. is my:last(.))]
                     | user[not(@method eq 'stop')][my:last(.)/@method eq 'stop']"/>

          <!-- Get the last user for this section & user id -->
          <xsl:function name="my:last">
            <xsl:param name="user"/>
            <xsl:sequence select="($user/../../section[@id eq $user/../@id]
                                              /user   [@id eq $user/@id]
                                  )
                                  [last()]"/>
          </xsl:function>
</xsl:transform>

結果は次のようになります。

<root>
    <node id="a">
        <section id="a_1">
            <item id="0">
                <attribute>
                    <color>
Red
                    </color>
                </attribute>
            </item>
        </section>
        <section id="a_2">
            <item id="0">
                <attribute>
                    <color>
Red
                    </color>
                </attribute>
            </item>
        </section>
    </node>
    <node id="b">
        <section id="b_1">
        </section>
        <section id="b_1" method="create">
            <user id="b_1a" method="stop">
                <attribute>
a
                </attribute>
            </user>
            <user id="b_1b" method="pause">
                <attribute>
a
                </attribute>
            </user>
        </section>
        <section id="b_2">
            <user id="b_1a" method="run">
                <attribute>
                    <name>
John
                    </name>
                </attribute>
            </user>
        </section>
    </node>
</root>

予想される出力は次のとおりです。

<root>
    <node id="a">
        <section id="a_1">
            <item id="0">
                <attribute>
                    <color>Red</color>
                </attribute>
            </item>
        </section>

        <section id="a_2">
            <item id="0">
                <attribute>
                    <color>Red</color>
                </attribute>
            </item>
        </section>            
    </node>

    <node id="b">
        <section id="b_1">                                           
        </section>

        <section id="b_1" method="create">               
            <user id="b_1a" method="stop">
                <attribute>a</attribute>
            </user>

            **<user id="b_1b" method="run">
                <attribute>a</attribute>
            </user>**
            <user id="b_1b" method="pause">
                <attribute>a</attribute>
            </user>
        </section>

        <section id="b_2">                
            <user id="b_1a" method="run">
                <attribute>
                    <name>John</name>
                </attribute>
            </user>
        </section>
    </node>
</root>

これが注文の仕組みです。「停止」が最後に発生した場合、同じユーザー ID (一時停止や実行など) を持つ他のメソッドを持つ他のノードは削除されます。ただし、そうでない場合は、「停止」自体のノードとその「停止」の前のすべてのノードが削除されます。

これは同じセクション ID で発生する必要があり、ユーザー ノードのみが削除されます (ユーザー ノードの削除後にセクション ID が空であっても、セクション ID はそのままになります)。説明が混乱しないことを願っています。

XSLTのみを使用してそれを行うことは可能ですか? または、各ノードをトラバースするために xQuery を使用する必要がありますか? 誰かが私を啓発できますか?どうもありがとうございました。

ジョン

4

1 に答える 1

2

XSLT 2.0 を使用したソリューションを次に示します。最初のルールは正規恒等変換です。2 番目のルールは、削除したいノードを削除します (私の理解が正しければ)。ユーザーの各リスト (私が理解しているように) は、セクション ID とユーザー ID の組み合わせによって識別されます。

<xsl:transform version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:my="http://localhost"
  exclude-result-prefixes="my">

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

  <!-- But remove the "stop" method if it's not last for the user/section;
       also, remove other methods where the last one is "stop" -->
  <xsl:template match="user[    @method eq 'stop' ][not(. is my:last(.))]
                     | user[not(@method eq 'stop')][my:last(.)/@method eq 'stop']"/>

          <!-- Get the last user for this section & user id -->
          <xsl:function name="my:last">
            <xsl:param name="user"/>
            <xsl:sequence select="($user/../../section[@id eq $user/../@id]
                                              /user   [@id eq $user/@id]
                                  )
                                  [last()]"/>
          </xsl:function>

</xsl:transform>

上記の仕組みについてご不明な点がございましたら、お問い合わせください。

于 2012-04-18T02:26:08.233 に答える