2017-01-26 11 views
1

для моего исследовательского проекта, у меня есть этот документ в формате XML/TEIXSL для-каждый на разделенных пробелами значений атрибутов

<TEI xmlns="http://www.tei-c.org/ns/1.0" > 
<body> 
    <div> 
     <p> 
      <span target="#" type="passage" ana="Tag957 Tag874"> 
       <span target="#" ana=""/> 
      </span> 
      <seg><date when="1980-01-01" type="date_seg"/>blabla blabla 
       blabla blablablabla blablablabla blablablabla blablablabla bl 
      </seg> 
      <span target="#" type="passage" ana="Tag1657 "> 
       <span target="#" ana=""/> 
      </span> 
      <seg><date from="1980-01-03" to="1980-01-05" type="date_seg"/>blabla 
      </seg> 
     </p> 
    </div> 
</body> 
</TEI> 

Мне нужно извлечь для каждого тега, содержащегося в пролете/@ ана: дата и длина строки следующего узла. С условием, что если мы включим атрибут date @from или @to, мне просто нужно значение @from. Что я должен был бы выглядеть так:

Tag957;1980-01-01;88 
Tag874;1980-01-01;88 
Tag1657;1980-01-03;11 

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

<xsl:template match="tei:p"> 
     <xsl:for-each select="tei:span"> 
       <xsl:value-of select="./@ana"/> 
       <xsl:text>;</xsl:text> 
      <xsl:if test="following-sibling::tei:seg/tei:date/@from or following-sibling::tei:seg/tei:date/@to"> 
       <xsl:value-of select="following-sibling::tei:seg/tei:date/@from"/> 
      </xsl:if> 
      <xsl:if test="following-sibling::tei:seg/tei:date/@when"> 
       <xsl:value-of select="following-sibling::tei:seg/tei:date/@when"/> 
      </xsl:if> 
       <xsl:text>;</xsl:text> 
       <xsl:value-of select="string-length(following-sibling::tei:seg)"/> 
       <xsl:text>;</xsl:text> 
       <xsl:value-of select="$newLine"/> 
     </xsl:for-each> 
</xsl:template> 
+1

Какой XSLT процессор, соответственно, которые XSLT версии сделать вы используете/можете использовать? –

+0

Я использую XSLT-процессор в программном обеспечении Oxygen, тот, который я выбрал, это Saxon-HE9.6.0.7 –

ответ

2

Использование XSLT 2.0 вы можете использовать tokenize, чтобы идентифицировать различные значения в значении атрибута, то вы можете переписать код, как

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xpath-default-namespace="http://www.tei-c.org/ns/1.0"> 
    <xsl:template match="p"> 
     <xsl:for-each select="span"> 
      <xsl:variable name="span" select="."/> 
      <xsl:for-each select="tokenize(@ana, '\s+')[normalize-space()]"> 
       <xsl:value-of select="."/> 
       <xsl:text>;</xsl:text> 
       <xsl:if test="$span/following-sibling::seg[1]/date/@from or $span/following-sibling::seg[1]/date/@to"> 
       <xsl:value-of select="$span/following-sibling::seg[1]/date/@from"/> 
       </xsl:if> 
       <xsl:if test="$span/following-sibling::seg/date/@when"> 
       <xsl:value-of select="$span/following-sibling::seg/date/@when"/> 
       </xsl:if> 
       <xsl:text>;</xsl:text> 
       <xsl:value-of select="string-length($span/following-sibling::seg[1])"/> 
       <xsl:text>;</xsl:text> 
       <xsl:value-of select="'&#10;'"/> 
      </xsl:for-each>  
     </xsl:for-each> 
    </xsl:template> 
</xsl:transform> 

онлайн на http://xsltransform.net/jz1PuPL.

+0

Спасибо, он отлично работал на XML, который я дал. Я протестировал его на других моих файлах, и мне пришлось добавить seg [1] во второй xsl: если причина - это получение дат всех других братьев sglg –

3

Вы сделано только одного цикла для span элементов. Этого не достаточно.

На самом деле, для каждого такого span вы должны:

  • Прочитайте атрибут ana.
  • Токсифицируйте его с помощью пробела (если можно, используйте XSLT 2.0, он имеет эту функцию).

Для каждых полученных маркеров (не для всей стоимости @ana) необходимо выполнить внутреннюю for-each петли:

  • Найти только первые следующие seg собрата и его ребенок date элемента: select="following-sibling::tei:seg[1]/tei:date" (обратите внимание, что я добавил [1]).
  • Проверьте, содержит ли он обязательные атрибуты (from, to или when).

Если это так, то:

  • печати текущий маркер извлекается из текущего атрибута ana.
  • Распечатайте требуемые даты в соответствии с вашими потребностями (с текущего элемента date).
  • Распечатайте остальную часть подлежащего печати.

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

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

1

XSLT-1.0

Я создаю рекурсивный шаблон для токенизации значений внутри атрибута ana и вызываю его для каждого интервала. Я должен был добавить пробел в строке 8 для шаблона работы: <xsl:with-param name="remaining-ana-val" select="substring-after(concat(./@ana,' '),' ')"/>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tei="http://www.tei-c.org/ns/1.0"> 
    <xsl:output method="text" omit-xml-declaration="yes" encoding="UTF-8"/> 
    <xsl:strip-space elements="*"/> 
    <xsl:template match="tei:p"> 
     <xsl:for-each select="tei:span"> 
      <xsl:call-template name="recurse_ana"> 
       <xsl:with-param name="ana_val" select="substring-before(./@ana,' ')"/> 
       <xsl:with-param name="remaining-ana-val" select="substring-after(concat(./@ana,' '),' ')"/> 
       <xsl:with-param name="seg" select="following-sibling::tei:seg[1]"/> 
      </xsl:call-template> 
     </xsl:for-each> 
    </xsl:template> 
    <xsl:template name="recurse_ana"> 
     <xsl:param name="ana_val"/> 
     <xsl:param name="remaining-ana-val"/> 
     <xsl:param name="seg"/> 
     <xsl:if test="string-length($ana_val) > 0"><xsl:value-of select="$ana_val"/> 
      <xsl:value-of select="';'"/> 
      <xsl:value-of select="$seg/tei:date/(@when|@from)"/> 
      <xsl:value-of select="';'"/> 
      <xsl:value-of select="string-length($seg)"/> 
      <xsl:value-of select="'&#x0D;'"/> 
      <xsl:call-template name="recurse_ana"> 
       <xsl:with-param name="ana_val" select="substring-before($remaining-ana-val,' ')"/> 
       <xsl:with-param name="remaining-ana-val" select="substring-after($remaining-ana-val,' ')"/> 
       <xsl:with-param name="seg" select="$seg"/> 
      </xsl:call-template> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

Выход:

Tag957;1980-01-01;105 
Tag874;1980-01-01;105 
Tag1657;1980-01-03;19 

Интернет ссылка: http://xsltransform.net/gWEamLJ/2

+0

Спасибо за ваше предложение. Я тестировал его на других файлах, и оказалось, что он только обрабатывает промежуток, который имеет несколько значений в @ana, а не те, у которых только одно значение. Странно :-) –

+0

@ r.let Второй интервал в вашем примере XML имеет и дополнительное пространство внутри атрибута ana. Я использую его для обозначения значений атрибутов. Возможно, у другого 'span' нет этого дополнительного атрибута и, следовательно, не учитывается. – Madeyedexter