3

xsltで変換する必要があるこの入力XMLがあります

<root>
    <node id="a">
        <section id="a_1" method="run">
            <item id="0">
                <attribute>
                    <color>Red</color>
                </attribute>
            </item>
        </section>
        <section id="a_2">
            <item id="0">
                <attribute>
                    <color>Red</color>
                </attribute>
            </item>
        </section>
        <section id="a_1" method="run">
            <item id="0">
                <attribute>
                    <color>Red</color>
                </attribute>
            </item>
        </section>
    </node>
    <node id="b">
        <section id="b_1" method="create">
            <user id="b_1a">
                <attribute>
                    <name>John</name>
                </attribute>
            </user>
            <user id="b_1b">
                <attribute>a</attribute>
            </user>
        </section>
        <section id="b_1" method="create">
            <user id="b_1c">
                <attribute>a</attribute>
            </user>
        </section>
        <section id="b_2">
            <user id="b_1a">
                <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" method="create">
            <user id="b_1a">
                <attribute>
                    <name>John</name>
                </attribute>
            </user>
            <user id="b_1b">
                <attribute>a</attribute>
            </user>
        </section>

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

同じ要素名、ID、およびメソッドを持っている限り、どのノードが削除されるかは問題ではなく、そのうちの 1 つが削除されます。xslがどのように見えるか考えていますか?

注: 要素名は何でもかまいません。ファイル全体に複数の要素名があります。要素名、id、および属性 (例: method=create) が同じである限り、そのうちの 1 つが削除されます。

どうもありがとう。乾杯、ジョン

4

2 に答える 2

3

I. 以下は、簡潔で効率的な (キーを使用した) XSLT 1.0 変換です。

<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="kElemWithAttribs" match="*[@id and @method]"
  use="concat(name(), '+', @id, '+', @method)"/>

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

 <xsl:template match=
  "*[@id and @method
    and
     not(generate-id()
        =
         generate-id(key('kElemWithAttribs',
                         concat(name(), '+', @id, '+', @method)
                         )[1]
                    )
         )
     ]"/>
</xsl:stylesheet>

この変換が提供された XML ドキュメントに適用されると、次のようになります。

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

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

<root>
   <node id="a">
      <section id="a_1" method="run">
         <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" method="create">
         <user id="b_1a">
            <attribute>
               <name>John</name>
            </attribute>
         </user>
         <user id="b_1b">
            <attribute>a</attribute>
         </user>
      </section>
      <section id="b_2">
         <user id="b_1a">
            <attribute>
               <name>John</name>
            </attribute>
         </user>
      </section>
   </node>
</root>

説明:

Muenchian メソッドを使用して、複合キーでグループ化します。ここでは、グループの最初ではないすべてのノードを無視 (削除) します。


Ⅱ.XSLT 2.0 ソリューション - さらに短く、効率も悪くない:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

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

    <xsl:for-each-group select="*"
         group-by="concat(name(), '+', @id, '+', @method)">
      <xsl:apply-templates select="."/>
    </xsl:for-each-group>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

説明:

属性xsl:for-each-groupとの適切な使用。group-by

于 2012-04-22T14:32:41.090 に答える
1

XSLファイル:

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

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

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

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

<xsl:template match="section[@id = 'b_1'][1]">  
    <section>
        <xsl:copy-of select="node()|@*"/>
    </section>  
</xsl:template>

<xsl:template match="section[@id != 'b_1']">
    <section>       
        <xsl:copy-of select="node()|@*"/>
    </section>
</xsl:template>

<xsl:template match="section[@id = 'b_1'][position() &gt; 1]"/> 

</xsl:stylesheet>

変換:

<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" method="create">
                <user id="b_1a">
                    <attribute>
                        <name>John</name>
                    </attribute>
                </user>
                <user id="b_1b">
                    <attribute>a</attribute>
                </user>
            </section>
            <section id="b_2">
                <user id="b_1a">
                    <attribute>
                        <name>John</name>
                    </attribute>
                </user>
            </section>
        </node>
    </root>

お役に立てれば。

[編集] 同じ入力ファイルでこのXSLを試してください:

<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

    <xsl:template match="*[not(@id eq preceding::*[local-name() eq local-name(.)]/@id)]">
        <xsl:element name="{name()}">
            <xsl:copy-of select="node()|@*"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

そして結果:

<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" method="create">
      <user id="b_1a">
        <attribute>
          <name>John</name>
        </attribute>
      </user>
      <user id="b_1b">
        <attribute>a</attribute>
      </user>
    </section>
    <section id="b_1" method="create">
      <user id="b_1c">
        <attribute>a</attribute>
      </user>
    </section>
    <section id="b_2">
      <user id="b_1a">
        <attribute>
          <name>John</name>
        </attribute>
      </user>
    </section>
  </node>
</root>

[/編集]

于 2012-04-22T08:37:59.713 に答える