XSL и как удалить дубликаты - PullRequest
0 голосов
/ 10 марта 2019

У меня проблема с записью преобразования xslt.Я хочу показать столбец со значениями из узла: Records / Record / PersonalData / PersonalDataDetail Для каждого человека в: Root / Data / Response / Person

Итак, я начал с отображения всех значений - код ниже:

translation.xsl

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    <table border="1">
    <xsl:for-each select="Root/Data/Response/Person">
    <tr>
      <td><xsl:value-of select="Name"/></td>
      <td>
    <xsl:for-each select="Records/Record/PersonalData/PersonalDataDetail[(@title='Country1' or @title='Country2' or @title='Country3')]">
      <xsl:value-of select="."/>
      <xsl:element name="br"/>
    </xsl:for-each>
      </td>
    </tr>
    </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

Пример данных:

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="transformation.xsl"?>

<Root>
    <Data>
        <Response>
            <Person>
                <Name>Robert A.</Name>
                <Records>
                    <Record>
                        <PersonalData>
                            <PersonalDataDetail title="Lucky Number">529</PersonalDataDetail>
                            <PersonalDataDetail title="Favorite Color">Blue</PersonalDataDetail>
                        </PersonalData>
                    </Record>
                </Records>
            </Person>
            <Person>
                <Name>Robert B.</Name>
                <Records>
                    <Record>
                        <PersonalData>
                            <PersonalDataDetail title="Lucky Number">3</PersonalDataDetail>
                            <PersonalDataDetail title="Country1">USA</PersonalDataDetail>
                        </PersonalData>
                    </Record>
                    <Record>
                        <PersonalData>
                            <PersonalDataDetail title="Favorite Color">Red</PersonalDataDetail>
                            <PersonalDataDetail title="Country2">UK</PersonalDataDetail>
                        </PersonalData>
                    </Record>
                    <Record>
                        <PersonalData>
                            <PersonalDataDetail title="Flight">AAA000</PersonalDataDetail>
                            <PersonalDataDetail title="Country2">UK</PersonalDataDetail>
                        </PersonalData>
                    </Record>
                </Records>
            </Person>
            <Person>
                <Name>Robert C.</Name>
                <Records>
                    <Record>
                        <PersonalData>
                            <PersonalDataDetail title="Lucky Number">529</PersonalDataDetail>
                            <PersonalDataDetail title="Country1">UK</PersonalDataDetail>
                        </PersonalData>
                    </Record>
                    <Record>
                        <PersonalData>
                            <PersonalDataDetail title="Country3">Argentina</PersonalDataDetail>
                        </PersonalData>
                    </Record>
                    <Record>
                        <PersonalData>
                            <PersonalDataDetail title="Country3">Argentina</PersonalDataDetail>
                            <PersonalDataDetail title="Flight">BBB000</PersonalDataDetail>
                        </PersonalData>
                    </Record>
                </Records>
            </Person>
        </Response>
    </Data>
</Root>

Текущий результат

Теперь я пытаюсь удалить дубликаты,но только на уровне человека.Я попытался изменить для каждого:

Записи / Запись / PersonalData / PersonalDataDetail [ не (. = Предыдущий :: *) и (@ title = 'Country1' или @ title ='Country2' или @ title = 'Country3')]

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

Не могли бы вы мне помочь?Я должен использовать XSLT 1.0.

1 Ответ

1 голос
/ 10 марта 2019

Предпочтительным методом удаления дубликатов в XSLT 1.0 является мюнхенская группировка .Сложность в вашем случае заключается в том, что вы хотите группировать только по элементу Person предка.Это решается добавлением уникального идентификатора Person к ключу группировки:

XSLT 1.0

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

<xsl:key name="country" match="PersonalDataDetail[starts-with(@title, 'Country')]" use="concat(., '|', generate-id(ancestor::Person))" />

<xsl:template match="/Root">
    <html>
        <body>
            <table border="1">
                <xsl:for-each select="Data/Response/Person">
                    <xsl:variable name="person-id" select="generate-id()" />
                    <tr>
                        <td>
                            <xsl:value-of select="Name"/>
                        </td>
                        <td>
                            <xsl:for-each select="Records/Record/PersonalData/PersonalDataDetail[starts-with(@title, 'Country')][count(. | key('country', concat(., '|', $person-id))[1]) = 1]">
                                <xsl:value-of select="."/>
                                <br/>
                            </xsl:for-each>
                        </td>
                    </tr>
                </xsl:for-each>
            </table>
        </body>
    </html>
</xsl:template>

</xsl:stylesheet>

Тем не менее, некоторые XSLT 1.0Процессоры поддерживают функцию расширения EXSLT set:distinct(), которая позволяет упростить процесс до:

XSLT 1.0 + EXSLT

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:set="http://exslt.org/sets"
extension-element-prefixes="set">

<xsl:template match="/Root">
    <html>
        <body>
            <table border="1">
                <xsl:for-each select="Data/Response/Person">
                    <xsl:variable name="person-id" select="generate-id()" />
                    <tr>
                        <td>
                            <xsl:value-of select="Name"/>
                        </td>
                        <td>
                            <xsl:for-each select="set:distinct(Records/Record/PersonalData/PersonalDataDetail[starts-with(@title, 'Country')])">
                                <xsl:value-of select="."/>
                                <br/>
                            </xsl:for-each>
                        </td>
                    </tr>
                </xsl:for-each>
            </table>
        </body>
    </html>
</xsl:template>

</xsl:stylesheet>
...