Как перечислить только уникальные пары из XML с использованием таблицы стилей XSLT? - PullRequest
1 голос
/ 22 ноября 2011

Это моя структура XML:

<dblp>

<inproceedings key="aaa" mdate="bbb">
<author>author1</author>
<author>author2</author>
<author>author3</author>
<title>Title of pubblications</title>
<pages>12345</pages>
<year>12345</year>
<crossref>sometext</crossref>
<booktitle>sometext</booktitle>
<url>sometext</url>
<ee>sometext</ee>
</inproceedings>

<article key="aaa" mdate="bbb">
<author>author1</author>
<author>author4</author>
<title>Title of pubblications</title>
<pages>12345</pages>
<year>12345</year>
<crossref>sometext</crossref>
<booktitle>sometext</booktitle>
<url>sometext</url>
<ee>sometext</ee>
</article>

<article key="aaa" mdate="bbb">
<author>author1</author>
<author>author2</author>
<title>Title of pubblications</title>
<pages>12345</pages>
<year>12345</year>
<crossref>sometext</crossref>
<booktitle>sometext</booktitle>
<url>sometext</url>
<ee>sometext</ee>
</article>

<inproceedings key="aaa" mdate="bbb">
<author>author2</author>
<author>author1</author>
<author>author5</author>
<title>Title of pubblications</title>
<pages>12345</pages>
<year>12345</year>
<crossref>sometext</crossref>
<booktitle>sometext</booktitle>
<url>sometext</url>
<ee>sometext</ee>
</inproceedings>

</dblp>

Мне нужно отобразить все пары авторов, которые сотрудничали для статьи (и материалов).

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

<xsl:variable name="papers" select="dblp/*"/>
        <xsl:for-each select="$papers">
            <xsl:for-each select="author[position() != last()]">
                <xsl:variable name="a1" select="."/>
                <xsl:for-each select="following-sibling::author">
                    <xsl:value-of select="concat(translate(translate(translate($a1,' ','_'),'.',''),&quot;'&quot;,' '), '--', translate(translate(translate(.,' ','_'),'.',''),&quot;'&quot;,' '), ';&#10;')"/>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:for-each>

Токовый выход:

author1--auhtor2
author1--auhtor3
author2--auhtor3
author1--auhtor4
author1--auhtor2
author2--auhtor1
author2--auhtor5
author1--auhtor5

Вывод должен быть таким:

author1--auhtor2
author1--auhtor3
author2--auhtor3
author1--auhtor4
---
---
author2--auhtor5
author1--auhtor5

Ответы [ 3 ]

1 голос
/ 22 ноября 2011

Решение XSLT 2.0:

<xsl:for-each-group select="/*/*/author" group-by=".">
    <xsl:sort select="current-grouping-key()"/>
    <xsl:variable name="firstKey" select="current-grouping-key()"></xsl:variable>
    <xsl:for-each-group select="/*/*/author[compare(.,  current-grouping-key()) = 1][some $x in (current-group()) satisfies $x/parent::* intersect ./parent::*]" group-by=".">
        <xsl:value-of select="concat($firstKey, '--',current-grouping-key(),';&#10;')"></xsl:value-of>
    </xsl:for-each-group>    
</xsl:for-each-group>  
0 голосов
/ 22 ноября 2011

Это преобразование XSLT 2.0: полное, короткое и хорошо отформатированное (27 строк):

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:key name="kAuthorBySibling" match="author"
     use="preceding-sibling::author | following-sibling::author"/>

    <xsl:variable name="vAuthors" as="element()*">
      <xsl:for-each select="distinct-values(/*/*/author)">
       <xsl:sort/>
       <a><xsl:value-of select="."/></a>
      </xsl:for-each>
    </xsl:variable>

 <xsl:template match="/">
     <xsl:sequence select=
      "for $a1 in $vAuthors,
         $doc in /,
           $a2 in $vAuthors
                   [. gt $a1
                  and
                    . = key('kAuthorBySibling', $a1, $doc)
                   ]

        return ($a1/string(), $a2/string(), '&#xA;')
      "/>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<dblp>
    <inproceedings key="aaa" mdate="bbb">
        <author>author1</author>
        <author>author2</author>
        <author>author3</author>
        <title>Title of pubblications</title>
        <pages>12345</pages>
        <year>12345</year>
        <crossref>sometext</crossref>
        <booktitle>sometext</booktitle>
        <url>sometext</url>
        <ee>sometext</ee>
    </inproceedings>
    <article key="aaa" mdate="bbb">
        <author>author1</author>
        <author>author4</author>
        <title>Title of pubblications</title>
        <pages>12345</pages>
        <year>12345</year>
        <crossref>sometext</crossref>
        <booktitle>sometext</booktitle>
        <url>sometext</url>
        <ee>sometext</ee>
    </article>
    <article key="aaa" mdate="bbb">
        <author>author1</author>
        <author>author2</author>
        <title>Title of pubblications</title>
        <pages>12345</pages>
        <year>12345</year>
        <crossref>sometext</crossref>
        <booktitle>sometext</booktitle>
        <url>sometext</url>
        <ee>sometext</ee>
    </article>
    <inproceedings key="aaa" mdate="bbb">
        <author>author2</author>
        <author>author1</author>
        <author>author5</author>
        <title>Title of pubblications</title>
        <pages>12345</pages>
        <year>12345</year>
        <crossref>sometext</crossref>
        <booktitle>sometext</booktitle>
        <url>sometext</url>
        <ee>sometext</ee>
    </inproceedings>
</dblp>

дает требуемый, правильный результат :

 author1 author2
 author1 author3 
 author1 author4 
 author1 author5 
 author2 author3 
 author2 author5 

Пояснение :

  1. Переменная $vAuthors представляет собой последовательность элементов a, набор строковых значений которых представляет собой набор различных значений элементов author в документе XML.a элементы отсортированы в этой последовательности.

  2. Ключ 'kAuthorBySibling' идентифицирует любой элемент `author (по строковому значению) любого из его родных элементов.

  3. Для каждого $a1 в $vAuthors мы получим любое $a2 в $vAuthors со строковым значением, большим, чем $a1, и таким, что элемент author со строковым значением, равным этому$a2 - это элемент из элемента author со строковым значением, равным $a1.Для этого мы просто проверяем (используя оператор общего равенства), находится ли строковое значение $a2 в наборе строковых значений key('kAuthorBySibling', $a1, $doc).

0 голосов
/ 22 ноября 2011

Для этого вы можете использовать элемент xslt xsl: for-each-group или функцию Different-values ​​().

В приведенном ниже шаблоне я поместил ваш генератор последовательности в переменную с именем round1, чтобы он мог быть обработан для удаления дубликатов. Я изменил внутренний цикл, чтобы создать элемент (collab) с парой атрибутов (которая соответствует вашему спариванию) и упорядоченной версией cannonicalPair. Чтобы каноническая пара использовалась для устранения дубликатов, поступали разные авторы. Обратите внимание, что иногда порядок сотрудничества значим в реальном мире.

После переменной round1 идет серия циклов, которые удаляют дубликаты. Первые два показывают, что вы можете вывести любой порядок сотрудничества в вашем наборе данных. В последнем случае коллаборации не рассматриваются как дубликаты, если они имеют другой порядок.

  <xsl:template match="/">

<xsl:variable name="papers" select="dblp/*"/> 
<xsl:variable name="round1">
        <xsl:for-each select="$papers"> 
            <xsl:for-each select="author[position() != last()]"> 
                <xsl:variable name="a1" select="."/> 
                <xsl:for-each select="following-sibling::author"> 
                    <xsl:element name="collab">
                      <xsl:attribute name="pair"  select="concat(translate(translate(translate($a1,' ','_'),'.',''),&quot;'&quot;,' '), '--', translate(translate(translate(.,' ','_'),'.',''),&quot;'&quot;,' '), ';&#10;')"/> 
                      <xsl:attribute name="cannonicalPair">
                        <xsl:choose>
                          <xsl:when test="$a1 lt ." >
                            <xsl:sequence select="concat(translate(translate(translate($a1,' ','_'),'.',''),&quot;'&quot;,' '), '--', translate(translate(translate(.,' ','_'),'.',''),&quot;'&quot;,' '), ';&#10;')" />
                          </xsl:when>
                          <xsl:otherwise>
                            <xsl:sequence select="concat(translate(translate(translate(.,' ','_'),'.',''),&quot;'&quot;,' '), '--', translate(translate(translate($a1,' ','_'),'.',''),&quot;'&quot;,' '), ';&#10;')" />
                          </xsl:otherwise>
                        </xsl:choose>
                      </xsl:attribute>  
                    </xsl:element>
                </xsl:for-each> 
            </xsl:for-each> 
        </xsl:for-each> 
</xsl:variable>

<xsl:text>&#x0A;</xsl:text>

<xsl:for-each-group select="$round1/collab" group-by="@cannonicalPair">
  <xsl:value-of select="current-group()[1]/@pair" />
</xsl:for-each-group>

<xsl:text>---- listing seperator ----&#x0A;</xsl:text>

<xsl:for-each-group select="$round1/collab" group-by="@cannonicalPair">
  <xsl:value-of select="current-group()[last()]/@pair" />
</xsl:for-each-group>

<xsl:text>---- listing seperator ----&#x0A;</xsl:text>

<xsl:for-each select="distinct-values($round1/collab/@cannonicalPair)">
  <xsl:value-of select="." />
</xsl:for-each>

<xsl:text>---- listing seperator ----&#x0A;</xsl:text>

<xsl:for-each select="distinct-values($round1/collab/@pair)">
  <xsl:value-of select="." />
</xsl:for-each>

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