Удаление повторяющихся элементов с использованием различных значений и xslt 2.0

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

Я немного поигрался с этим, и приведенный ниже код выглядит так, как будто я думал, что он сработает, но я получаю сообщение об ошибке:

XPTY0020: ведущий '/' не может выбрать корневой узел дерева, содержащего элемент контекста: элемент контекста не является узлом

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <xsl:strip-space elements="*"/>
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">

        <xsl:for-each select="distinct-values(/tobject/tobject.subject/@tobject.subject.refnum)">
            <xsl:copy-of select="."/>
        </xsl:for-each>

    </xsl:template>
</xsl:stylesheet>

XML:

<?xml version="1.0" encoding="UTF-8"?>
<tobject tobject.type="Utenriks">
    <tobject.property tobject.property.type="Nyheter"/>
    <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04000000" tobject.subject.type="økonomi og næringsliv"/>
    <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04000000" tobject.subject.type="økonomi og næringsliv"/>
    <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04000000" tobject.subject.type="økonomi og næringsliv"/>
    <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04005000" tobject.subject.matter="olje og energi"/>
    <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04000000" tobject.subject.type="økonomi og næringsliv"/>
    <tobject.subject tobject.subject.code="POL" tobject.subject.refnum="11000000" tobject.subject.type="politikk"/>
    <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04000000" tobject.subject.type="økonomi og næringsliv"/>
    <tobject.subject tobject.subject.code="POL" tobject.subject.refnum="11000000" tobject.subject.type="politikk"/>
    <tobject.subject tobject.subject.code="POL" tobject.subject.refnum="11003000" tobject.subject.matter="valg"/>
    <tobject.subject tobject.subject.code="KRE" tobject.subject.refnum="02000000" tobject.subject.type="kriminalitet og rettsvesen"/>
    <tobject.subject tobject.subject.code="FRI" tobject.subject.refnum="10000000" tobject.subject.type="fritid"/>
</tobject>

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

<?xml version="1.0" encoding="UTF-8"?>
<tobject tobject.type="Utenriks">
    <tobject.property tobject.property.type="Nyheter"/>
    <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04000000" tobject.subject.type="økonomi og næringsliv"/>
    <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04005000" tobject.subject.matter="olje og energi"/>
    <tobject.subject tobject.subject.code="POL" tobject.subject.refnum="11000000" tobject.subject.type="politikk"/>
    <tobject.subject tobject.subject.code="POL" tobject.subject.refnum="11003000" tobject.subject.matter="valg"/>
    <tobject.subject tobject.subject.code="KRE" tobject.subject.refnum="02000000" tobject.subject.type="kriminalitet og rettsvesen"/>
    <tobject.subject tobject.subject.code="FRI" tobject.subject.refnum="10000000" tobject.subject.type="fritid"/>
</tobject>

person Trond    schedule 11.11.2015    source источник


Ответы (2)


приведенный ниже код выглядит так, как я думал, будет работать, но я получаю сообщение об ошибке:

XPTY0020: ведущий '/' не может выбрать корневой узел дерева, содержащего элемент контекста: элемент контекста не является узлом

Эту ошибку невозможно воспроизвести, запустив ваш код - см. http://xsltransform.net/gWvjQfa

Однако результатом distinct-values() является последовательность значений, а не узлов. Ожидаемого результата - удаления повторяющихся элементов - гораздо проще добиться с помощью группировки:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/tobject">
    <xsl:copy>
        <xsl:copy-of select="@* | tobject.property"/>
        <xsl:for-each-group select="tobject.subject" group-by="@tobject.subject.refnum">
            <xsl:copy-of select="current-group()[1]"/>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>
person michael.hor257k    schedule 11.11.2015

I. Еще более короткое решение , которое представляет собой чистый XSLT 1.0 и не требует ненужных имен элементов.

Кроме того, он не менее эффективен, чем решение XSLT 2.0, использующее <xsl:for-each-group>, потому что здесь мы используем метод Мюнхи для группировки:

<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="kOS" match="tobject.subject" use="@tobject.subject.refnum"/>

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

  <xsl:template match=
  "tobject.subject[generate-id() != generate-id(key('kOS', @tobject.subject.refnum)[1])]"/>
</xsl:stylesheet>

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

<tobject tobject.type="Utenriks">
    <tobject.property tobject.property.type="Nyheter"/>
    <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04000000" tobject.subject.type="økonomi og næringsliv"/>
    <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04000000" tobject.subject.type="økonomi og næringsliv"/>
    <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04000000" tobject.subject.type="økonomi og næringsliv"/>
    <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04005000" tobject.subject.matter="olje og energi"/>
    <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04000000" tobject.subject.type="økonomi og næringsliv"/>
    <tobject.subject tobject.subject.code="POL" tobject.subject.refnum="11000000" tobject.subject.type="politikk"/>
    <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04000000" tobject.subject.type="økonomi og næringsliv"/>
    <tobject.subject tobject.subject.code="POL" tobject.subject.refnum="11000000" tobject.subject.type="politikk"/>
    <tobject.subject tobject.subject.code="POL" tobject.subject.refnum="11003000" tobject.subject.matter="valg"/>
    <tobject.subject tobject.subject.code="KRE" tobject.subject.refnum="02000000" tobject.subject.type="kriminalitet og rettsvesen"/>
    <tobject.subject tobject.subject.code="FRI" tobject.subject.refnum="10000000" tobject.subject.type="fritid"/>
</tobject>

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

<tobject tobject.type="Utenriks">
   <tobject.property tobject.property.type="Nyheter"/>
   <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04000000" tobject.subject.type="økonomi og næringsliv"/>
   <tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04005000" tobject.subject.matter="olje og energi"/>
   <tobject.subject tobject.subject.code="POL" tobject.subject.refnum="11000000" tobject.subject.type="politikk"/>
   <tobject.subject tobject.subject.code="POL" tobject.subject.refnum="11003000" tobject.subject.matter="valg"/>
   <tobject.subject tobject.subject.code="KRE" tobject.subject.refnum="02000000" tobject.subject.type="kriminalitet og rettsvesen"/>
   <tobject.subject tobject.subject.code="FRI" tobject.subject.refnum="10000000" tobject.subject.type="fritid"/>
</tobject>

II. Однострочное выражение XPath 2.0, которое выбирает желаемый уникальный (по одному из каждого элемента группы

$vElems[index-of($vElems/@tobject.subject.refnum, @tobject.subject.refnum)[1]]

Здесь $ vElems должен быть определен как:

/*/tobject.subject

Когда это выражение XPath 2.0 оценивается в предоставленном XML-документе, выбирается желаемая последовательность элементов:

<tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04000000"
             tobject.subject.type="økonomi og næringsliv"/>
<tobject.subject tobject.subject.code="OKO" tobject.subject.refnum="04005000"
             tobject.subject.matter="olje og energi"/>
<tobject.subject tobject.subject.code="POL" tobject.subject.refnum="11000000"
             tobject.subject.type="politikk"/>
<tobject.subject tobject.subject.code="POL" tobject.subject.refnum="11003000"
             tobject.subject.matter="valg"/>
<tobject.subject tobject.subject.code="KRE" tobject.subject.refnum="02000000"
             tobject.subject.type="kriminalitet og rettsvesen"/>
<tobject.subject tobject.subject.code="FRI" tobject.subject.refnum="10000000"
             tobject.subject.type="fritid"/>
person Dimitre Novatchev    schedule 12.11.2015