Удалите дублирующиеся элементы XML, используя XSLT с perl XML :: LibXSLT - PullRequest
1 голос
/ 07 июля 2019

У меня есть этот XML-файл:

<?xml version="1.0" encoding="UTF-8"?>
<d:dictionary xmlns="http://www.w3.org/1999/xhtml" xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
    <d:entry id="a" d:title="a">
        <d:index d:value="a" d:title="a"/>
        <d:index d:value="b" d:title="b"/>
        <d:index d:value="a" d:title="a"/>
        <d:index d:value="c" d:title="c"/>
        <d:index d:value="b" d:title="b"/>
        <d:index d:value="a" d:title="a"/>
        <d:index d:value="b" d:title="b"/>
        <div>This is the content for entry.</div>
    </d:entry>
    <d:entry id="b" d:title="b">
        <d:index d:value="a" d:title="a"/>
        <d:index d:value="b" d:title="b"/>
        <div>This is the content for entry.</div>
    </d:entry>
</d:dictionary>

Я пытаюсь удалить дубликаты <d:index записей, используя XSLT после этой публикации: https://stackoverflow.com/a/56898207/589924

Примечание. Каждая запись имеет свой собственный независимый <d:index, т.е. один и тот же индекс в разных записях не должен считаться дубликатом.И полученный xml должен соответствовать исходному формату xml.

Файл xsl выглядит следующим образом:

<xsl:stylesheet version="2.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
<xsl:template>
    <xsl:copy>
        <xsl:for-each-group select="d:index"
                            group-by="concat(@d:value, '~', @d:title)">
            <xsl:copy-of select="current-group()[1]"/>
        </xsl:for-each-group>
        <xsl:copy-of select="div"/>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

Но результат не ожидается, он удаляет все теги, кромедля содержания div.

<?xml version="1.0"?>









This is the content for entry.




This is the content for entry.

Ответы [ 2 ]

3 голосов
/ 07 июля 2019

Использование метода Мюнхена для группировки :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" exclude-result-prefixes="d">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:key name="kIndexByValueTitle" match="d:index"
          use="concat(generate-id(..), '+', @d:value, '+', @d:title)"/>

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

  <xsl:template match=
   "d:index[not(generate-id()
               = generate-id(key('kIndexByValueTitle',
                                  concat(generate-id(..), '+', @d:value, '+', @d:title)
                                 )
                                  [1]))]" />
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному документу XML :

<d:dictionary xmlns="http://www.w3.org/1999/xhtml"
 xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
    <d:entry id="a" d:title="a">
        <d:index d:value="a" d:title="a"/>
        <d:index d:value="b" d:title="b"/>
        <d:index d:value="a" d:title="a"/>
        <d:index d:value="c" d:title="c"/>
        <d:index d:value="b" d:title="b"/>
        <d:index d:value="a" d:title="a"/>
        <d:index d:value="b" d:title="b"/>
        <div>This is the content for entry.</div>
    </d:entry>
    <d:entry id="b" d:title="b">
        <d:index d:value="a" d:title="a"/>
        <d:index d:value="b" d:title="b"/>
        <div>This is the content for entry.</div>
    </d:entry>
</d:dictionary>

желаемый, правильный результат получается :

<d:dictionary xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" xmlns="http://www.w3.org/1999/xhtml">
   <d:entry id="a" d:title="a">
      <d:index d:value="a" d:title="a"/>
      <d:index d:value="b" d:title="b"/>
      <d:index d:value="c" d:title="c"/>
      <div>This is the content for entry.</div>
   </d:entry>
   <d:entry id="b" d:title="b">
      <d:index d:value="a" d:title="a"/>
      <d:index d:value="b" d:title="b"/>
      <div>This is the content for entry.</div>
   </d:entry>
</d:dictionary>
1 голос
/ 08 июля 2019

Иногда использование библиотек прямого программирования может быть проще.Следуя сценарию Perl, используя XML :: DT

#!/usr/bin/perl
use XML::DT;
my $filename = shift;
my %seen=();

my %handler=(
    'd:entry' => sub{ %seen=(); toxml },                     ## reset seen
    'd:index' => sub{ if ($seen{$v{"d:value"}}++){""    }    ## $v{id} -- attribute id 
                      else                       {toxml}},
);
print dt($filename, %handler);

как обычно, sudo cpan XML::DT, если не установлен.

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