2012-05-21 2 views
2

Я хотел бы, чтобы удалить последовательного дубликат узла из же родителя и который также имеет точно такое же ребенок.Как удалить этот сложный XML-дублирующий узел с помощью XSLT?

ввода Сценарий 1:

<myroot> 
    <nodeA id="a"> 
     <section id="i"> 
      <item1 id="0" method="create"> 
       <somechild>a</somechild> 
      </item1> 

      <item1 id="1" method="create"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section>   

     <section id="i"> 
      <item1 id="0" method="create"> <!-- second consecutive create, we remove this --> 
       <somechild>a</somechild> 
      </item1> 
      <item1 id="0" method="create"> <!-- third consecutive create, but children have different value , so we don't remove this --> 
       <somechild>bbb</somechild> 
      </item1> 
      <item1 id="3" method="create"> 
       <other>xx</other>  
      </item1> 

      <item1 id="0" method="change"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section> 
    </nodeA> 

    <nodeA id="b"> 
     <section id="i"> 
      <item1 id="0" method="create"> 
       <somechild>a</somechild> 
      </item1> 

      <item1 id="1" method="create"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section>   

     <section id="i"> 
      <item1 id="0" method="create"> <!-- second consecutive create, we remove this --> 
       <somechild>a</somechild> 
      </item1> 
      <item1 id="0" method="create"> <!-- third consecutive create, but children have different value , so we don't remove this --> 
       <somechild>bbb</somechild> 
      </item1> 
      <item1 id="3" method="create"> 
       <other>xx</other>  
      </item1> 

      <item1 id="0" method="change"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section> 
    </nodeA> 

    <nodeB id="b"> 
     <section id="i"> 
      <item1 id="0" method="create"> 
       <somechild>a</somechild> 
      </item1> 

      <item1 id="1" method="create"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section>   

     <section id="i"> 
      <item1 id="0" method="create"> <!-- second consecutive create, we remove this --> 
       <somechild>a</somechild> 
      </item1> 
      <item1 id="0" method="create"> <!-- third consecutive create, but children have different value , so we don't remove this --> 
       <somechild>bbb</somechild> 
      </item1> 
      <item1 id="3" method="create"> 
       <other>xx</other>  
      </item1> 

      <item1 id="0" method="change"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section> 
    </nodeB> 
</myroot> 

Мой результат:

<myroot> 
    <nodeA id="a"> 
     <section id="i"> 
      <item1 id="0" method="create"> 
       <somechild>a</somechild> 
      </item1> 
      <item1 id="1" method="create"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section> 
     <section id="i"> 
      <item1 id="0" method="create"> 
       <somechild>bbb</somechild> 
      </item1> 
      <item1 id="3" method="create"> 
       <other>xx</other> 
      </item1> 
      <item1 id="0" method="change"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section> 
    </nodeA> 
    <nodeA id="b"> 
     <section id="i"/> 
     <section id="i"/> 
    </nodeA> 
    <nodeB id="b"> 
     <section id="i"/> 
     <section id="i"/> 
    </nodeB> 
</myroot> 

Ожидаемый результат:

<myroot> 
    <nodeA id="a"> 
     <section id="i"> 
      <item1 id="0" method="create"> 
       <somechild>a</somechild> 
      </item1> 

      <item1 id="1" method="create"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section>   

     <section id="i"> 
      <item1 id="0" method="create"> 
       <somechild>bbb</somechild> 
      </item1> 
      <item1 id="3" method="create"> 
       <other>xx</other>  
      </item1> 

      <item1 id="0" method="change"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section> 
    </nodeA> 

    <nodeA id="b"> 
     <section id="i"> 
      <item1 id="0" method="create"> 
       <somechild>a</somechild> 
      </item1> 

      <item1 id="1" method="create"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section>   

     <section id="i"> 
      <item1 id="0" method="create"> 
       <somechild>bbb</somechild> 
      </item1> 
      <item1 id="3" method="create"> 
       <other>xx</other>  
      </item1> 

      <item1 id="0" method="change"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section> 
    </nodeA> 

    <nodeB id="b"> 
     <section id="i"> 
      <item1 id="0" method="create"> 
       <somechild>a</somechild> 
      </item1> 

      <item1 id="1" method="create"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section>   

     <section id="i"> 
      <item1 id="0" method="create"> 
       <somechild>bbb</somechild> 
      </item1> 
      <item1 id="3" method="create"> 
       <other>xx</other>  
      </item1> 

      <item1 id="0" method="change"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section> 
    </nodeB> 
</myroot> 

В первом сценарии выше: только второй раз подряд создать имеет у одних и тех же детей и третьего последовательного метода create есть разные дети, поэтому мы удаляем только второй.

Второй вход сценарий (больше вариантов):

<myroot> 
    <nodeB id="a"> 
     <cell id="i">    
      <item2 id="1" method="create"> 
       <otherchild>a</otherchild> 
      </item2> 

      <item2 id="0" method="create"> 
       <otherchild>a</otherchild> 
      </item2> 

      <item2 id="1" method="modify"> 
       <otherchild>a</otherchild> 
      </item2>   
     </cell>   

     <cell id="i"> 
      <item2 id="1" method="modify"> <!-- second consecutive modify, we remove this --> 
       <otherchild>a</otherchild> 
      </item2> 

      <item2 id="1" method="modify"> <!-- third consecutive modify, BUT different chldren, we do NOT remove this --> 
       <otherchild>a</otherchild> 
       <somechild>aa</somechild> 
      </item2> 

      <item2 id="1" method="delete" /> 

      <item2 id="0" method="create"> 
       <somechild>bbb</somechild> 
      </item2> 

      <item2 id="1" method="delete" /> <!-- second consecutive delete, we remove this --> 

      <item2 id="3" method="create"> 
       <other>xx</other>  
      </item2> 

      <item2 id="1" method="delete" /> <!-- third consecutive delete, we remove this -->   
     </cell> 
    </nodeB> 
</myroot> 

Выход:

<myroot> 
    <nodeB id="a"> 
     <cell id="i">    
      <item2 id="1" method="create"> 
       <otherchild>a</otherchild> 
      </item2> 

      <item2 id="0" method="create"> 
       <otherchild>a</otherchild> 
      </item2> 

      <item2 id="1" method="modify"> 
       <otherchild>a</otherchild> 
      </item2>   
     </cell>   

     <cell id="i"> 
      <item2 id="1" method="modify"> 
       <otherchild>a</otherchild> 
       <somechild>aa</somechild> 
      </item2> 

      <item2 id="1" method="delete" /> 

      <item2 id="0" method="create"> 
       <somechild>bbb</somechild> 
      </item2>   
     </cell> 
    </nodeB> 
</myroot> 

Не работает над этим:

<myroot>  
     <node1 id="a"> 
      <section id="i"> 
       <item1 id="0" method="start"> 
        <somechild>a</somechild> 
       </item1> 
       <item1 id="0" method="start"> <!-- this one is successive from the previous so we eliminate --> 
        <somechild>a</somechild> 
       </item1> 
       <item1 id="0" method="stop"/>     
       <item1 id="0" method="start"> <!-- this will be treated as new starting point --> 
        <somechild>a</somechild> 
       </item1> 
      </section> 

      <section id="i"> 
       <item1 id="0" method="start"> <!-- this one is successive from the previous so we eliminate --> 
        <somechild>a</somechild> 
       </item1> 
      </section>     
     </node1> 
    </myroot> 

output: 

    <myroot>  
     <node1 id="a"> 
      <section id="i"> 
       <item1 id="0" method="start"> 
        <somechild>a</somechild> 
       </item1> 
       <item1 id="0" method="start"> <!-- this one is successive from the previous so we eliminate --> 
        <somechild>a</somechild> 
       </item1> 
       <item1 id="0" method="stop"/>       
      </section>     
      <section id="i"/>        
     </node1> 
    </myroot> 

The correct output should be: 

    <myroot>  
     <node1 id="a"> 
      <section id="i"> 
       <item1 id="0" method="start"> 
        <somechild>a</somechild> 
       </item1>     
       <item1 id="0" method="stop"/>     
       <item1 id="0" method="start"> <!-- this will be treated as new starting point --> 
        <somechild>a</somechild> 
       </item1> 
      </section>     
      <section id="i" />     
     </node1> 
    </myroot> 

Может кто-нибудь помог мне с этим запутанный удаление с помощью XSLT? Чрезвычайно очень.

Джон

+0

Джон, вы можете использовать XSLT 2.0 (как реализовано Saxon или AltovaXML или XMLPrime)? У этого есть 'for-each-group' и' deep-equal'. Если вы хотите использовать XSLT 1.0, сколько дочерних узлов и имен элементов есть, они полностью произвольны? –

+0

@MartinHonnen да, я могу использовать XSLT 2.0. Да, дочерний узел произволен, но метод только создает, изменяет и удаляет. Только узел с методом удаления не имеет дочерних элементов. – John

ответ

5

Вот XSLT 2.0 пример таблицы стилей, которые должны выполнять работу или, по крайней мере, дать вам представление о том, как с помощью deep-equal может помочь:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="2.0"> 

    <xsl:strip-space elements="*"/> 
    <xsl:output indent="yes"/> 

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

    <xsl:template match="/*/*/*/*[some $el in (preceding-sibling::* , preceding::*) satisfies deep-equal(., $el)]"/> 

</xsl:stylesheet> 

[править] С новым требованием I не вижу способ решить, что с deep-equal только поэтому я написал новую таблицу стилей, которая использует for-each-group и deep-equal:

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="2.0"> 

    <xsl:strip-space elements="*"/> 
    <xsl:output indent="yes"/> 

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

    <xsl:template match="/*/*"> 
    <xsl:copy> 
     <xsl:variable name="first-in-group" as="element()*"> 
     <xsl:for-each-group select="*" group-by="concat(node-name(.), '|', @id)"> 
      <xsl:for-each-group select="current-group()/*" group-by="concat(@id, '|', @method)"> 
      <xsl:sequence 
       select="for $pos in 1 to count(current-group()) 
         return current-group()[$pos] 
           [every $item 
           in subsequence(current-group(), 1, $pos - 1) 
           satisfies not(deep-equal($item, current-group()[$pos]))] "/> 
      </xsl:for-each-group> 
     </xsl:for-each-group> 
     </xsl:variable> 
     <xsl:apply-templates select="@*"/> 
     <xsl:apply-templates> 
     <xsl:with-param name="first-in-group" select="$first-in-group" tunnel="yes"/> 
     </xsl:apply-templates> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="/*/*/*/*"> 
    <xsl:param name="first-in-group" tunnel="yes"/> 
    <xsl:if test="$first-in-group intersect ."> 
     <xsl:call-template name="identity"/> 
    </xsl:if> 
    </xsl:template> 

</xsl:stylesheet> 

С этой таблицей стилей саксонской 9,4, при нанесении на образец

<myroot> 
    <nodeA id="a"> 
     <section id="i"> 
      <item1 id="0" method="create"> 
       <somechild>a</somechild> 
      </item1> 

      <item1 id="1" method="create"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section>   

     <section id="i"> 
      <item1 id="0" method="create"> <!-- second consecutive create, we remove this --> 
       <somechild>a</somechild> 
      </item1> 
      <item1 id="0" method="create"> <!-- third consecutive create, but children have different value , so we don't remove this --> 
       <somechild>bbb</somechild> 
      </item1> 
      <item1 id="3" method="create"> 
       <other>xx</other>  
      </item1> 

      <item1 id="0" method="change"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section> 
    </nodeA> 

    <nodeA id="b"> 
     <section id="i"> 
      <item1 id="0" method="create"> 
       <somechild>a</somechild> 
      </item1> 

      <item1 id="1" method="create"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section>   

     <section id="i"> 
      <item1 id="0" method="create"> <!-- second consecutive create, we remove this --> 
       <somechild>a</somechild> 
      </item1> 
      <item1 id="0" method="create"> <!-- third consecutive create, but children have different value , so we don't remove this --> 
       <somechild>bbb</somechild> 
      </item1> 
      <item1 id="3" method="create"> 
       <other>xx</other>  
      </item1> 

      <item1 id="0" method="change"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section> 
    </nodeA> 

    <nodeB id="b"> 
     <section id="i"> 
      <item1 id="0" method="create"> 
       <somechild>a</somechild> 
      </item1> 

      <item1 id="1" method="create"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section>   

     <section id="i"> 
      <item1 id="0" method="create"> <!-- second consecutive create, we remove this --> 
       <somechild>a</somechild> 
      </item1> 
      <item1 id="0" method="create"> <!-- third consecutive create, but children have different value , so we don't remove this --> 
       <somechild>bbb</somechild> 
      </item1> 
      <item1 id="3" method="create"> 
       <other>xx</other>  
      </item1> 

      <item1 id="0" method="change"> 
       <otherchild>a</otherchild> 
      </item1> 
     </section> 
    </nodeB> 
</myroot> 

выходы

<myroot> 
    <nodeA id="a"> 
     <section id="i"> 
     <item1 id="0" method="create"> 
      <somechild>a</somechild> 
     </item1> 
     <item1 id="1" method="create"> 
      <otherchild>a</otherchild> 
     </item1> 
     </section> 
     <section id="i"> 
     <item1 id="0" method="create"><!-- third consecutive create, but children have different value , so we don't re 
move this --><somechild>bbb</somechild> 
     </item1> 
     <item1 id="3" method="create"> 
      <other>xx</other> 
     </item1> 
     <item1 id="0" method="change"> 
      <otherchild>a</otherchild> 
     </item1> 
     </section> 
    </nodeA> 
    <nodeA id="b"> 
     <section id="i"> 
     <item1 id="0" method="create"> 
      <somechild>a</somechild> 
     </item1> 
     <item1 id="1" method="create"> 
      <otherchild>a</otherchild> 
     </item1> 
     </section> 
     <section id="i"> 
     <item1 id="0" method="create"><!-- third consecutive create, but children have different value , so we don't re 
move this --><somechild>bbb</somechild> 
     </item1> 
     <item1 id="3" method="create"> 
      <other>xx</other> 
     </item1> 
     <item1 id="0" method="change"> 
      <otherchild>a</otherchild> 
     </item1> 
     </section> 
    </nodeA> 
    <nodeB id="b"> 
     <section id="i"> 
     <item1 id="0" method="create"> 
      <somechild>a</somechild> 
     </item1> 
     <item1 id="1" method="create"> 
      <otherchild>a</otherchild> 
     </item1> 
     </section> 
     <section id="i"> 
     <item1 id="0" method="create"><!-- third consecutive create, but children have different value , so we don't re 
move this --><somechild>bbb</somechild> 
     </item1> 
     <item1 id="3" method="create"> 
      <other>xx</other> 
     </item1> 
     <item1 id="0" method="change"> 
      <otherchild>a</otherchild> 
     </item1> 
     </section> 
    </nodeB> 
</myroot> 

подачка надеюсь, все будет удален вы хотите удалить, и все хранится вы хотите сохранить.

+0

Это действительно здорово! Большое спасибо за ваше решение. – John

+0

Извините, после более тщательного тестирования кажется, что решение не учитывает, что это происходит только в текущем узле A/nodeB с таким же идентификатором (например, nodeA id = "a"), потому что может быть другой в одном файле. Не могли бы вы обновить его, чтобы отразить это состояние? Если вам нужно, чтобы я добавил еще один пример, пожалуйста, дайте мне знать. Огромное спасибо. – John

+0

Джон, пожалуйста, напишите больше образцов, чтобы проиллюстрировать ваши требования, например, текущий образец, который у вас есть, где сбой таблицы стилей, выход, который вы хотите в этом случае, и тот, который вы получите. –

Смежные вопросы