-5

输入文件:

<root>
    <sector>
        <nodeA id="a">
            <section id="i">
                <item1 id="1" method="create"> 
                    <somechild>a</somechild>
                </item1>

                <item1 id="1" method="delete" />
            </section>                   
        </nodeA>

        <nodeA id="b">
            <cell id="ii">  
                <item2 id="2" method="create"> 
                    <otherchild>a</otherchild>
                </item2>
            </cell>
            <cell id="ii">
                <item2 id="2" method="delete" />
            </cell>                   
        </nodeA>

        <nodeB id="i">
            <cell id="ii">  
                <item3 id="1" method="create"> 
                    <child>b</child>
                </item3>
            </cell>

            <cell id="ii">
                <item3 id="1" method="delete" />
                <item3 id="1" method="create"> 
                    <otherchild>a</otherchild>
                </item3>
            </cell>                   
        </nodeB>
    </sector> 
</root>

预期输出:

<root>
    <sector>
        <nodeA id="a">
            <section id="i">
            </section>                   
        </nodeA>

        <nodeA id="b">
            <cell id="ii">  
            </cell>
            <cell id="ii">
            </cell>                   
        </nodeA>

        <nodeB id="i">
            <cell id="ii">  
                <item3 id="1" method="create"> <!-- this is not eliminated as it violates the rule by having create followed by delete and followed by create again -->
                    <child>b</child>
                </item3>
            </cell>

            <cell id="ii">
                <item3 id="1" method="delete" />
                <item3 id="1" method="create"> 
                    <otherchild>a</otherchild>
                </item3>
            </cell>                   
        </nodeB>
    </sector> 
</root>

我需要使用此规则消除 xml 中的节点:

  • 一个节点method="create"跟随 一个节点method="delete"将被淘汰
  • 该场景可以发生在一个父级中,也可以在两个父级中传播,只要它具有相同的元素名称和 id<cell id="ii">

如何使用 XSLT 1.0 或 2.0 进行这种转换?

谢谢你。

4

1 回答 1

1

这是一种方法。您定义一个键来对要删除的项目进行分组。我认为您是按元素的@id 属性以及两个父节点的@id 属性进行分组的

<xsl:key 
   name="items" 
   match="*[@method != '']" use="concat(@id, '|', ../@id, '|', ../../@id)" />

接下来,您可以有一个模板来匹配您的@method='create'项目,其中键中有两个元素,另一个项目是@method='delete'

<xsl:template match="*
   [@method = 'create']
   [count(key('items', concat(@id, '|', ../@id, '|', ../../@id))) = 2]
   [key('items', concat(@id, '|', ../@id, '|', ../../@id))[@method = 'delete']]" />

您还需要一个模板以类似的方式匹配其他@method='delete' 。

这是完整的 XSLT

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

   <xsl:key name="items" match="*[@method != '']" use="concat(@id, '|', ../@id, '|', ../../@id)" />

   <xsl:template match="*[@method = 'create'][count(key('items', concat(@id, '|', ../@id, '|', ../../@id))) = 2][key('items', concat(@id, '|', ../@id, '|', ../../@id))[@method = 'delete']]" />
   <xsl:template match="*[@method = 'delete'][count(key('items', concat(@id, '|', ../@id, '|', ../../@id))) = 2][key('items', concat(@id, '|', ../@id, '|', ../../@id))[@method = 'create']]" />

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

应用于您的示例 XML 时,将输出以下内容

<root>
   <sector>
      <nodeA id="a">
         <section id="i"/>
      </nodeA>
      <nodeA id="b">
         <cell id="ii"/>
         <cell id="ii"/>
      </nodeA>
      <nodeB id="i">
         <cell id="ii">
            <item3 id="1" method="create">
               <child>b</child>
            </item3>
         </cell>
         <cell id="ii">
            <item3 id="1" method="delete"/>
            <item3 id="1" method="create">
               <otherchild>a</otherchild>
            </item3>
         </cell>
      </nodeB>
   </sector>
</root>
于 2012-05-24T22:15:39.383 回答