XSLT последняя позиция в атрибуте - PullRequest
2 голосов
/ 31 мая 2011

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

<xsl:if test="position() = last()">

, похоже, не принимает во внимание значение атрибута.

Вот XML

<creators and-others="no">
            <creator type="personal">Roche, R.L.</creator> 
            <creator type="personal">Moulin, D.</creator> 
            <creator type="personal">James, K.</creator> 
            <creator type="affiliation">CEA Centre d'Etudes Nucleaires de Saclay, 91 - Gif-sur-  zYvette (France). Dept. d'Etudes Mecaniques et Thermiques</creator> 
</creators>

Мне нужен вывод как, Roche, R.L., Moulin, D., & James, K.

Кроме того, есть ли способ получить количество значений для узла «создатель» с атрибутом «личный»?

Ответы [ 5 ]

1 голос
/ 31 мая 2011

Вы можете попробовать итерировать по <xsl:for-each select="creator[@type='personal']"> и использовать там <xsl:if>. XPath должен выбрать все те элементы, для которых атрибут type имеет значение personal.

Вы можете использовать подобное выражение в функции count.

1 голос
/ 31 мая 2011

Почему бы не подсчитать следующих братьев и сестер внутри соответствующего шаблона? Последний узел creator[@type='personal'], следующий за родным братом, будет равен нулю.

XSLT 2.0 протестировано под Saxon-HE 9.2.1.1J (также работает как XSLT 1.0 на MSXSL 4.0 )

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

    <xsl:output method="text"/>

    <xsl:template match="/creators">
        <xsl:apply-templates select="creator"/>
    </xsl:template>

    <xsl:template match="creator[@type='personal']">
        <xsl:choose>
            <xsl:when test="count(following-sibling::creator[@type='personal'])=0">
                <xsl:text>&amp; </xsl:text><xsl:value-of select="."/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="."/><xsl:text>, </xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="creator"/>

</xsl:stylesheet>

Применительно к вашему входу, выдает:

Roche, R.L., Moulin, D., & James, K.

В соответствии с контекстом шаблона вы всегда можете использовать ось, чтобы получить количество узлов. Пример:

<xsl:template match="/creators">
    <xsl:variable name="count" select="count(child::creator[@type='personal'])"/>
</xsl:template>

установит $count в 3.

0 голосов
/ 31 мая 2011

Вот более короткое решение, которое вообще не использует никаких условных инструкций XSLT:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
   <xsl:apply-templates select="creator[@type='personal']"/>
 </xsl:template>

 <xsl:template match=
  "creator[@type='personal'][position()>1 and not(position()=last())]">
  <xsl:text>, </xsl:text>
  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="creator[@type='personal'][position()=last()]">
  <xsl:text>, &amp; </xsl:text>
  <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>

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

<creators and-others="no">
    <creator type="personal">Roche, R.L.</creator>
    <creator type="personal">Moulin, D.</creator>
    <creator type="personal">James, K.</creator>
    <creator type="affiliation">CEA Centre d'Etudes Nucleaires de Saclay, 91 - Gif-sur-  zYvette (France). Dept. d'Etudes Mecaniques et Thermiques</creator>
</creators>

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

Roche, R.L., Moulin, D., & James, K.

Кроме того, есть ли способ, чтобы получить счет значений для узла «создатель», с атрибут "личный"?

Используйте

count(/*/creator[@type='personal'])

Пояснение

  1. Использование сопоставления с образцом вместо условных инструкций XSLT.

  2. Использование модели обработки XSLT (по умолчанию) и встроенных шаблонов.

0 голосов
/ 31 мая 2011

Используйте предикат [@type='personal'], чтобы выбрать только нужные элементы <creator>. Тогда ваше тестовое условие работает без использования каких-либо подсчетов или ссылок на элементы одного уровня. Вы также должны проверить, есть ли только один <creator type="personal">, в противном случае вы в конечном итоге выведите дополнительные & или запятую. Поэтому <xsl:choose> здесь удобнее, чем <xsl:if> в одиночку.

Пример кода ниже. Вы также можете использовать <xsl:for-each select="creator[@type='personal']"> вместо отдельного шаблона для creator и вызова <xsl:apply-templates select="creator[@type='personal']"/>, если вы хотите сделать это внутри существующего шаблона.

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

<xsl:output method="text"/>

<xsl:template match="creators">
    <xsl:apply-templates select="creator[@type='personal']"/>
</xsl:template>

<xsl:template match="creator">
        <xsl:choose>
            <xsl:when test="position() = 1">
            </xsl:when>
            <xsl:when test="position() = last()">
                <xsl:text> &amp; </xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>, </xsl:text>
            </xsl:otherwise>
        </xsl:choose>
        <xsl:value-of select="."/>
</xsl:template>

</xsl:stylesheet>

С учетом ввода

<creators and-others="no">
            <creator type="personal">Roche, R.L.</creator>
            <creator type="personal">Moulin, D.</creator>
            <creator type="personal">James, K.</creator>
            <creator type="affiliation">CEA Centre d'Etudes Nucleaires de Saclay, 91 - Gif-sur-  zYvette (France). Dept. d'Etudes Mecaniques et Thermiques</creator>
</creators>

выдает следующий вывод

Roche, R.L., Moulin, D. & James, K.
0 голосов
/ 31 мая 2011

Это должно работать

  <xsl:if test="count(//creator[@type='personal']) &gt; 0">
    Found personal
  </xsl:if>

Если вы хотите сохранить его в переменной

<xsl:variable name="PersonalCount" select="count(//creator[@type='personal'])"></xsl:variable>
...