Удалите повторяющийся тег и его дочерние элементы в XML с помощью XSLT - PullRequest
0 голосов
/ 02 августа 2020

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

Пример: xml выглядит так:

<root>
       <row>
            <title>The Oscars Opening Ceremony: Live from the Red Carpet</title>  <!-- here -->
            <actors>Margot Robbie</actors>
            <actors>Kumail Nanjiani</actors>
            <actors>Timothée Chalamet</actors>
            <actors>Matthew McConaughey</actors>
            <actors>Nicole Kidman</actors>
            <actors>Saoirse Ronan</actors>
            <actors>Jennifer Garner</actors>
            <actors>Armie Hammer</actors>
            <actors>Sandra Bullock</actors>
            <actors>Gary Oldman</actors>
            <actors>Mira Sorvino</actors>
            <actors>Salma Hayek</actors>
            <actors>Mahershala Ali</actors>
            <actors>Jordan Peele</actors>
            <actors>Wendi McLendon-Covey</actors>
            <description>The Oscars Opening</description>
        </row>
       <row>
            <title>Tabaluga tivi</title>
            <actors>Ben Bledsoe</actors>
            <actors>Philipp Wimmer</actors>
            <actors>Patrick King Jr.</actors>
            <description>Tabaluga tivi</description>
        </row>
        <row>
            <title>Library of God</title>
            <actors>Peter Førde</actors>
            <actors>Lasse Vermeli</actors>
            <actors>Hilde Amundsen</actors>
            <description>Library of God</description>
        </row>
        <row>
            <title>The Oscars Opening Ceremony: Live From The Red Carpet</title> <!-- here again -->
            <actors>Mel Gibson</actors>
            <actors>Dwayne Johnson</actors>
            <actors>Nicole Kidman</actors>
            <actors>Robin Roberts</actors>
            <actors>Meryl Streep</actors>
            <actors>Justin Timberlake</actors>
            <description>Interviews with nominees, presenters and performers arriving for the awards ceremony; hosts Robin Roberts, Michael Strahan and Lara Spencer.</description>
        </row>
</root>

Желаемый результат вывода:

<root>
        <row>
            <title>The Oscars Opening Ceremony: Live from the Red Carpet</title>  <!-- only this one at result -->
            <actors>Margot Robbie</actors>
            <actors>Kumail Nanjiani</actors>
            <actors>Timothée Chalamet</actors>
            <actors>Matthew McConaughey</actors>
            <actors>Nicole Kidman</actors>
            <actors>Saoirse Ronan</actors>
            <actors>Jennifer Garner</actors>
            <actors>Armie Hammer</actors>
            <actors>Sandra Bullock</actors>
            <actors>Gary Oldman</actors>
            <actors>Mira Sorvino</actors>
            <actors>Salma Hayek</actors>
            <actors>Mahershala Ali</actors>
            <actors>Jordan Peele</actors>
            <actors>Wendi McLendon-Covey</actors>
            <description>The Oscars Opening</description>
        </row>
       <row>
            <title>Tabaluga tivi</title>
            <actors>Ben Bledsoe</actors>
            <actors>Philipp Wimmer</actors>
            <actors>Patrick King Jr.</actors>
            <description>Tabaluga tivi</description>
        </row>
        <row>
            <title>Library of God</title>
            <actors>Peter Førde</actors>
            <actors>Lasse Vermeli</actors>
            <actors>Hilde Amundsen</actors>
            <description>Library of God</description>
        </row>
   </root>

Это xslt, который я использую:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kTitleByContent" match="row"
             use="concat(title, '+', actors, '+', description)"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="row[generate-id() !=
                              generate-id(key('kTitleByContent',
                                              concat(title,'+',
                                                     actors,'+',
                                                     description))[1])]"/>
</xsl:stylesheet>

Почему не удаляются дубликаты? Ценю любую помощь. Спасибо

1 Ответ

0 голосов
/ 02 августа 2020

Ключ, просто использующий элемент title, должен работать, если title - это все, что вы хотите сравнить, и они в точности равны:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    
  <xsl:key name="kRowByTitle" 
           match="row"
           use="title"/>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="row[generate-id() != generate-id(key('kRowByTitle', title)[1])]"/>

</xsl:stylesheet>

Обратите внимание, что, однако, в опубликованном вами образце у вас есть различия в случае букв в первом и четвертом title, поэтому вам может потребоваться дополнительно использовать функцию lower-case в XSLT 2 и более поздних версиях, или вам нужно объявить два параметра со всеми буквами, которые вам нужно обрабатывать в верхнем и нижнем регистре -case и используйте translate.

В XSLT 3 это будет просто

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="3.0">
    
  <xsl:key name="kRowByTitle" 
           match="row"
           use="lower-case(title)"/>

  <xsl:mode on-no-match="shallow-copy"/>
  
  <xsl:template match="row[not(. is key('kRowByTitle', lower-case(title))[1])]"/>

</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...