在xslt中对多个相同节点内容进行分组

时间:2014-09-06 14:26:16

标签: xml xslt xslt-1.0

我正在创建和使用XSLT文件将XML文件中的某些数据显示为CSV。 我坚持一个特定的方面,因为我找不到许多具有类似xml结构的在线示例。

鉴于这个假设的XML:

<collection>
 <book>
  <author> author1name </author>
  <author> author2name </author>
  <title> booktitle </title>
 </book>
 <book>
  <author> authorname </author>
  <title> booktitle </title>
 </book>
</collection>

和xslt:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" >
<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>

<xsl:template match="/">
author,title

<xsl:for-each select="//book">
<xsl:value-of select="concat

(author,',',title',','&#xA;')"/>
</xsl:for-each>

</xsl:template>
</xsl:stylesheet>

其中输出

author, title
author1name, booktitle
authorname, booktitle

请注意,输出中不包含author2。这是一个很大的数据丢失。 我试图使用嵌套的for循环来遍历所有作者,但我已经计算了太多的错误。

有人可以提出一种方法来产生

的输出
author1name;author2name, booktitle

第一本书? (两位作者用分号分隔)

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

您可以做的是创建一个匹配author的模板,您只需输出名称,如果不是第一作者,则在其前面加分号

<xsl:template match="author">
    <xsl:if test="position() > 1">;</xsl:if>
    <xsl:value-of select="." />
</xsl:template>

然后,要输出每本书,而不是将author放在concat语句中,请改用xsl:apply-templates

<xsl:apply-templates select="author" />
<xsl:value-of select="concat(',', title,'&#xA;')"/>

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
   <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>

   <xsl:template match="collection">
       <xsl:text>author,title</xsl:text>
       <xsl:value-of select="'&#xA;'" />
      <xsl:apply-templates select="book"/>
   </xsl:template>

   <xsl:template match="book">
      <xsl:apply-templates select="author"/>
      <xsl:value-of select="concat(',', title,'&#xA;')"/>
   </xsl:template>

   <xsl:template match="author">
      <xsl:if test="position() &gt; 1">;</xsl:if>
      <xsl:value-of select="."/>
   </xsl:template>
</xsl:stylesheet>

编辑:顺便说一下,将来,如果您能够使用XSLT 2.0,您可以使用separator运算符的xsl:value-of属性来实现相同的结果:

<xsl:value-of select="author" separator=";" />

答案 1 :(得分:0)

concat()是一个字符串函数;您无法将其应用于节点集。请尝试改为:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>

<xsl:template match="/">
    <xsl:text>author,title&#10;</xsl:text>
    <xsl:for-each select="collection/book">
        <xsl:for-each select="author">
            <xsl:value-of select="."/>
            <xsl:if test="position()!=last()">
                <xsl:text>;</xsl:text>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>,</xsl:text>
        <xsl:value-of select="title"/>
        <xsl:if test="position()!=last()">
            <xsl:text>&#10;</xsl:text>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>