xslt получает только одно значение из дубликатов в ключах и выводит как другое значение

Я работаю над следующим xml:

<?xml version="1.0" encoding="utf-8" ?>
 <root>
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     .....
     xmlns:dc="http://purl.org/dc/terms/">

  <skos:Concept rdf:about="http://aims.fao.org/aos/agrovoc/c_26321">
     .....
   <skos:prefLabel xml:lang="en">Abies mariesii</skos:prefLabel>
   <skos:broader rdf:resource="http://aims.fao.org/aos/agrovoc/c_10"/>
  </skos:Concept>

  <skos:Concept rdf:about="http://aims.fao.org/aos/agrovoc/c_33272">
     .....
   <skos:prefLabel xml:lang="en">Abies numidica</skos:prefLabel>
   <skos:broader rdf:resource="http://aims.fao.org/aos/agrovoc/c_10"/>
  </skos:Concept>

     .....

  <skos:Concept rdf:about="http://aims.fao.org/aos/agrovoc/c_5886">
     .....
   <skos:prefLabel xml:lang="en">Pinaceae</skos:prefLabel>
     .....
   <skos:narrower rdf:resource="http://aims.fao.org/aos/agrovoc/c_10"/>        
  </skos:Concept>

  <skos:Concept>
   <skos:narrower rdf:resource="http://aims.fao.org/skosmos/agrovoc/en/page/c_1322232213779"/>
   <skos:narrower rdf:resource="http://aims.fao.org/skosmos/agrovoc/en/page/c_19"/>
     .....
   <skos:prefLabel xml:lang="en">Abies</skos:prefLabel>
     .....
   <skos:closeMatch>

     .....

 </rdf:RDF>

Полный XML-файл доступен здесь: http://128.199.159.143/merged-file.xml

И у меня есть следующие XSLT (на основе node-tr">xslt получить значение элемента на основе атрибута, на который ссылается другое дерево узлов) здесь:

<?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   .....
 xmlns:void="http://rdfs.org/ns/void#">
 <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
 <xsl:key name="concepts-by-about" match="//skos:Concept" use="@rdf:about" />

  <xsl:template match="root">
   <xsl:for-each select="rdf:RDF">
   <xsl:text>START HERE</xsl:text>
   <xsl:text>&#13;&#10;</xsl:text>
   <xsl:text>=LDR  00000nam  2200000Ia 4500</xsl:text>
   <xsl:text>&#13;&#10;</xsl:text>
   <xsl:apply-templates select="skos:Concept/skos:broader" />
   <xsl:text>&#13;&#10;</xsl:text>
   <xsl:apply-templates select="skos:Concept/skos:narrower" />
   <xsl:text>&#13;&#10;</xsl:text>
   </xsl:for-each>
  </xsl:template>

  <xsl:template match="//skos:broader[key('concepts-by-about', @rdf:resource)]">       
   <xsl:text>=301  \\$abroader$b</xsl:text><xsl:value-of select="key('concepts-by-about', @rdf:resource)/skos:prefLabel[@xml:lang='en']" />
   <xsl:text>$c</xsl:text>
   <xsl:value-of select="./@rdf:resource" />
   <xsl:text>&#13;&#10;</xsl:text>   
  </xsl:template>           

  <xsl:template match="text()" />

  <xsl:template match="//skos:narrower[key('concepts-by-about', @rdf:resource)]">       
   <xsl:text>=302  \\$anarrower$b</xsl:text><xsl:value-of select="key('concepts-by-about', @rdf:resource)/skos:prefLabel[@xml:lang='en']" />
   <xsl:text>$c</xsl:text>
   <xsl:value-of select="./@rdf:resource" />
   <xsl:text>&#13;&#10;</xsl:text>   
  </xsl:template>           

  <xsl:template match="text()" />

  <xsl:template match="skos:Concept/skos:narrower/skos:Concept/skos:prefLabel[@xml:lang='en']">
   <xsl:text>=302  \\$anarrower$b</xsl:text><xsl:value-of select="." />
   <xsl:text>$c</xsl:text>
   <xsl:value-of select="../@rdf:about" />
   <xsl:text>&#13;&#10;</xsl:text>
  </xsl:template>

 </xsl:stylesheet>

С этим xslt я получаю следующее:

START HERE
=LDR  00000nam  2200000Ia 4500
=301  \\$abroader$bAbies$chttp://aims.fao.org/aos/agrovoc/c_10
=301  \\$abroader$bAbies$chttp://aims.fao.org/aos/agrovoc/c_10
  (more =301  \\$abroader$bAbies$chttp://aims.fao.org/aos/agrovoc/c_10) ...
=301  \\$abroader$bPinaceae$chttp://aims.fao.org/aos/agrovoc/c_5886

что меня устраивает, потому что это то, что я хотел с XML, основанным на http://aims.fao.org/skosmos/agrovoc/en/page/c_10, что Pinaceae является более широкой концепцией. Однако «Abies» повторяется несколько раз, так как мне удалить эти дубликаты и напечатать их как другое значение:

=400  \\$apreferredterm$bAbies$chttp://aims.fao.org/aos/agrovoc/c_10

person schnydszch    schedule 17.08.2015    source источник
comment
Обратите внимание, что использование XSLT в документе RDF/XML по своей сути рискованно. Существует множество RDF/XML-графиков, содержащих точно такое же RDF-содержимое, которое не будет работать с любым XSLT, который у вас получится. Один и тот же граф RDF можно сериализовать в XML множеством различных способов. См. этот ответ, чтобы узнать больше о проблемах с методами на основе XML, применяемыми к RDF/XML.   -  person Joshua Taylor    schedule 17.08.2015
comment
Можете ли вы обновить свой вопрос данными, которые фактически выводят ваш пример? После исправления XML и XSLT, чтобы сделать его действительным, я просто получаю =LDR 00000nam 2200000Ia 4500 (после НАЧАТЬ ЗДЕСЬ). Вам легче помочь, когда у нас есть реальный рабочий пример вашей проблемы.   -  person Abel    schedule 17.08.2015
comment
Привет, Джошуа, мой дополнительный вопрос: как мне вывести свои наборы данных в табличной или линейной форме? или в такой форме: aims.fao.org/skosmos/agrovoc/ ru/page/c_10   -  person schnydszch    schedule 17.08.2015
comment
Привет! Abel xml: 128.199.159.143/merged-file.xml, а xslt, который я над которым мы работали, находится здесь: 128.199.159.143/skos70.xsl   -  person schnydszch    schedule 17.08.2015


Ответы (1)


Я посмотрел на вашу таблицу стилей, на которую вы ссылаетесь, и там есть эта строка:

<xsl:template match="//skos:broader[key('concepts-by-about', @rdf:resource)]">

Поскольку ключи являются глобальными и существует по крайней мере один соответствующий ключу узел, конструкция [key(...)] всегда будет истинной (в предикате, если она соответствует узлу, она считается «истинной»). Вы можете убедиться в этом сами, если попробуете следующее на любом уровне:

<xsl:value-of select="count(//skos:broader[key('concepts-by-about', @rdf:resource)])" />

Он покажет вам, что есть 51 совпадение узлов. Вероятно, это не ваше намерение.

Мне кажется, что вы действительно хотите сопоставить skos:broader элементы, у которых есть родитель (или предок), который соответствует атрибуту @rdf-resource текущего узла с атрибутом @rdf:about skos:Concept. Вы можете сделать это следующим образом:

<xsl:template
    match="skos:broader[@rdf:resource = ancestor::skos:Concept/@rdf:about]">

После того, как я изменю это, на выходе будет только одно из следующего:

=301  \\$abroader$bAbies$chttp://aims.fao.org/aos/agrovoc/c_10

Затем внутри этого шаблона вы делаете:

<xsl:value-of
    select="key('concepts-by-about', @rdf:resource)/skos:prefLabel[@xml:lang = 'en']" />

Это вернет первое глобальное значение, соответствующее ключу. Опять же, мне кажется, что вы действительно хотите, чтобы предок skos:Concept был здесь, но я предполагаю. Если да, то должно быть (игнорируя совпадение на @rdf:about, потому что мы уже знаем, что это совпадение):

<xsl:value-of select="ancestor::skos:Concept/skos:prefLabel[@xml:lang = 'en']" />

Кроме того, есть несколько случаев, когда у вас есть шаблон соответствия, начинающийся с //, это не имеет никакого эффекта. Это означает «начиная с корня, любой узел на любом уровне, который соответствует тому, что следует». Но шаблон в любом случае уже является глобальным, поэтому он не имеет никакого эффекта, за исключением того, что вы просите процессор выполнять дорогостоящий поиск каждый раз, когда он сталкивается с этим шаблоном. Это верно для ключа и для некоторых соответствующих шаблонов.

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

person Abel    schedule 23.08.2015
comment
Я фактически отказался от этой стратегии перевода моего набора данных. Но я могу вернуться к этому снова. Да, я хотел бы сопоставить rdf:resource skos:broader (например, root/rdf:RDF/skos:Concept/skos:broader[@rdf:resource=aims.fao.org/skosmos/agrovoc/en/page/c_5886]) в Skos:Concept @rdf:about (root/rdf :RDF/skos:Concept[@rdf:about=aims.fao.org/aos/agrovoc /c_5886]), а затем, если они совпадают, я получаю значение xml:lang='en'. Я пробовал оба добавления шаблонов, но, похоже, что-то упустил. Вот текущий шаблон для справки: 128.199.159.143/skos73.xsl - person schnydszch; 24.08.2015
comment
@schnydszch: ваша таблица стилей работает, насколько я понимаю требования, строка 301 теперь выводится один раз с Abies как =301 \\$abroader$bAbies$chttp://aims.fao.org/aos/agrovoc/c_10. Но если вы можете, вам следует переключиться на XSLT 2.0, где та же задача намного проще с использованием синтаксиса xsl:for-each-group. - person Abel; 26.08.2015
comment
@schnydszch: если мое решение помогло вам, не стесняйтесь голосовать и/или принимать его как ответ;) - person Abel; 28.08.2015