XSLT-преобразование, конкатенация строк - PullRequest
1 голос
/ 02 марта 2011

У меня есть следующий xml

<R N="14" MIME="application/pdf">
    <RK>7</RK>
    <MT N="Abstract"
        V="Lorem Ipsum is simply dummy text of the printing " />
    <MT N="Abstract1"
  V="and typesetting industry. Lorem Ipsum has been the industry's standard "/>
    <MT N="Author" V="Bernard Shaw;" />
    <MT N="Author1" V="Mark Twain" />
    <MT N="Abstract2"
   V="dummy text ever since the 1500s, when an unknown printer took a galley"/>
    <LANG>en</LANG>
</R>

При преобразовании с помощью XSLT мне нужно объединить поля Abstract и Author и показать его как

Abstract: Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley

Author: Bernard Shaw;Mark Twain

Abstract, Abstract1, Abstract2 может появляться в любом порядке в xml.

Я пытаюсь использовать что-то вроде ниже, но застрял на условие и конкатенацию строки, когда Abstract, Abstract1 не появляется в том же порядке

<xsl:template match="MT">
    <xsl:if test="(some generic condition to display Title)">
        <br/>
        <span class="f">
            <xsl:value-of select="@N"/>
        </span>
    </xsl:if>
    <xsl:value-of select="@V"/>
</xsl:template>

Ценю любую помощь.

Ответы [ 3 ]

2 голосов
/ 02 марта 2011

Это преобразование :

<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="/">
     Abstract: <xsl:text/>
     <xsl:for-each select="*/MT[starts-with(@N, 'Abstract')]">
       <xsl:value-of select="@V"/>
     </xsl:for-each>
   Author: <xsl:text/>
     <xsl:for-each select="*/MT[starts-with(@N, 'Author')]">
       <xsl:value-of select="@V"/>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

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

<R N="14" MIME="application/pdf">
    <RK>7</RK>
    <MT N="Abstract" V="Lorem Ipsum is simply dummy text of the printing " />
    <MT N="Abstract1" V="and typesetting industry. Lorem Ipsum has been the industry's standard " />
    <MT N="Author" V="Bernard Shaw;" />
    <MT N="Author1" V="Mark Twain" />
    <MT N="Abstract2" V="dummy text ever since the 1500s, when an unknown printer took a galley" />
    <LANG>en</LANG>
</R>

создает искомыйрезультат:

Abstract: Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley
Author: Bernard Shaw;Mark Twain

Дальнейший рефакторинг :

<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="/">
     Abstract: <xsl:text/>
     <xsl:call-template name="concatAttributes"/>
   Author: <xsl:text/>
     <xsl:call-template name="concatAttributes">
      <xsl:with-param name="pKeyStartString" select="'Author'"/>
     </xsl:call-template>
 </xsl:template>

 <xsl:template name="concatAttributes">
  <xsl:param name="pKeyAttribName" select="'N'"/>
  <xsl:param name="pKeyStartString" select="'Abstract'"/>
  <xsl:param name="pValueAttribName" select="'V'"/>

     <xsl:for-each select=
      "*/MT[starts-with(@*[name()=$pKeyAttribName], $pKeyStartString)]">
       <xsl:value-of select="@*[name()=$pValueAttribName]"/>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Второй рефакторинг (запрошенный ОП):

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>
    <xsl:variable name="vAbstract">
        <xsl:apply-templates mode="retrieve" select="//MT"/>
    </xsl:variable>
    <xsl:variable name="vAuthors">
        <xsl:apply-templates mode="retrieve" select="//MT">
            <xsl:with-param name="pKeyStartString" select="'Author'"/>
        </xsl:apply-templates>
    </xsl:variable>

    <xsl:template match="/">
     Abstract: <xsl:value-of select="$vAbstract"/>
     Authors:: <xsl:value-of select="$vAuthors"/>
    </xsl:template>

    <xsl:template match="MT" mode="retrieve">
        <xsl:param name="pKeyAttribName" select="'N'"/>
        <xsl:param name="pKeyStartString" select="'Abstract'"/>
        <xsl:param name="pValueAttribName" select="'V'"/>
        <xsl:if test="starts-with(@*[name()=$pKeyAttribName], $pKeyStartString)">
            <xsl:value-of select="@*[name()=$pValueAttribName]"/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

РЕДАКТИРОВАТЬ : ОП запросил, чтобы "вся обработка выполнялась в шаблоне, соответствующем MT".Хотя это возможно в простых случаях (см. Ответ @ Alejandro), выполнение всей обработки в одном шаблоне, соответствующем MT, открывает большие промежутки неизвестных.Например, может потребоваться обработать другие MT элементы другим способом, и в этом случае такая обработка вообще не будет выполняться.

В более сложных случаях (например, когда приходят элементы и атрибуты)в любом порядке, но выходные данные должны быть отсортированы (Abstract1, Abstract2, ..., Abstract-N), тогда сортировка должна быть указана явно, и это должно быть вне шаблона, соответствующего MT. Поэтому, в общем случае, невозможно получить требуемый вывод с кодом только в пределах сопоставления шаблона MT.

Я бы порекомендовал сопоставление одного шаблонаMT находиться в именованном режиме и что его следует использовать в "стиле стиля" - применяется явно вызывающим абонентом.

0 голосов
/ 02 марта 2011

Эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kMtByAlphaN"
             match="MT"
             use="concat(generate-id(..),'+',translate(@N,'1234567890',''))"/>
    <xsl:template match="MT[count(.|key('kMtByAlphaN',
                                        concat(
                                           generate-id(..),'+',
                                           translate(@N,'1234567890','')
                                        )
                                    )[1]
                            ) = 1
                         ]">
        <xsl:variable name="vName"
                      select="translate(@N,'1234567890','')"/>
        <xsl:value-of select="concat($vName,': ')"/>
        <xsl:apply-templates select="key('kMtByAlphaN',
                                             concat(generate-id(..),'+',$vName)
                                     )/@V"/>
        <xsl:text>&#xA;</xsl:text>
    </xsl:template>
    <xsl:template match="text()"/>
</xsl:stylesheet>

Вывод:

Abstract: Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley
Author: Bernard Shaw;Mark Twain

Примечание : группировка по алфавиту @N и сгенерированному родителями идентификатору, поскольку я ожидаю несколько1009 * элементов.

0 голосов
/ 02 марта 2011
<xsl:for-each select="MT[starts-with(@N, 'Abstract')]">
    <xsl:if test="position() = 1">
        <xsl:value-of select="@N"/>:
    </xsl:if>
    <xsl:value-of select="@V"/>
</xsl:for-each>
...