xsl:for-each - 如何格式化列表?

时间:2014-09-27 18:11:26

标签: xml xslt

我是新来的,所以如果我无知,请原谅我。这是我的XML数据的一个示例。

<record ID="ART5843">
  <title>This is a sample record</title>
  <edition></edition>
  <persauthorfull>Lykins, Amy D.</persauthorfull>
  <persauthorfull>Cantor, James M.</persauthorfull>
  <persauthorfull>Blanchard, Ray</persauthorfull>
  <keywords>Generic</keywords>
  <keywords>Criminal offences</keywords>
  <keywords>Civil offences</keywords>
  <keywords>Men</keywords>
  <keywords>Psychology</keywords>
  <keywords>Research</keywords>
  <subjects></subjects>
</record>

我需要<persauthorfull>重命名为<PA>,然后输出一行用分号分隔,例如......

<PA>Lykins, Amy D.; Cantor, James M.; Blanchard, Ray</PA>

我使用XSL for-each来提取名称,但我不知道如何格式化它们。

<xsl:for-each select="a:persauthorfull">
  <PA>
    <xsl:attribute name="type">
    <xsl:value-of select="."/>
    </xsl:attribute>
  </PA>
</xsl:for-each> 

从我猜测这是对作者的一次迭代 - 还有另一种方式吗?

3 个答案:

答案 0 :(得分:1)

如果你想获得:

<PA>Lykins, Amy D.; Cantor, James M.; Blanchard, Ray</PA>

然后你应该做(在XSLT 1.0中):

<PA>
    <xsl:for-each select="persauthorfull">
        <xsl:value-of select="."/>
        <xsl:if test="position()!=last()">
            <xsl:text>; </xsl:text>
        </xsl:if>
    </xsl:for-each> 
</PA>

答案 1 :(得分:1)

如果您使用的是XSLT 2.0,那么string-join()就是您所需要的:

<PA>
   <xsl:value-of select="string-join(a:persauthorfull,'; ')"/>
</PA>

编辑:正如迈克尔凯所建议的,有一种更简单的方法:

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

使用任一行代码,所有persauthorfull元素的文本内容将被连接,由&#34;分隔; &#34;


让我也清楚你当前的代码是做什么的。你写道:

  

从我的猜测来看,这是对作者的单一迭代

这是真的 - 如果通过&#34;单次迭代&#34;你的意思是每个a:persauthorfull元素的一次迭代。如果有多个作者,这将在输出中创建多个PA元素。此外,作者的姓名最终还是属性type

<PA type="Blanchard, Ray"/>

<强>样式表

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="record">
        <xsl:copy>
            <xsl:apply-templates select="@*|persauthorfull[1]/preceding-sibling::*"/>
            <PA>
                <xsl:value-of select="string-join(persauthorfull,'; ')"/>
            </PA>
            <xsl:apply-templates select="persauthorfull[last()]/following-sibling::*"/>
        </xsl:copy>
    </xsl:template>  

</xsl:transform>

XML输入

<record ID="ART5843">
  <title>This is a sample record</title>
  <edition></edition>
  <persauthorfull>Lykins, Amy D.</persauthorfull>
  <persauthorfull>Cantor, James M.</persauthorfull>
  <persauthorfull>Blanchard, Ray</persauthorfull>
  <keywords>Generic</keywords>
  <keywords>Criminal offences</keywords>
  <keywords>Civil offences</keywords>
  <keywords>Men</keywords>
  <keywords>Psychology</keywords>
  <keywords>Research</keywords>
  <subjects></subjects>
</record>

XML输出

<record ID="ART5843">
   <title>This is a sample record</title>
   <edition/>
   <PA>Lykins, Amy D.; Cantor, James M.; Blanchard, Ray</PA>
   <keywords>Generic</keywords>
   <keywords>Criminal offences</keywords>
   <keywords>Civil offences</keywords>
   <keywords>Men</keywords>
   <keywords>Psychology</keywords>
   <keywords>Research</keywords>
   <subjects/>
</record>

答案 2 :(得分:0)

以下XSLT生成输出,可以调整以满足未知的进一步要求:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/*">
<PA>
   <xsl:apply-templates select="persauthorfull"/>
</PA>
</xsl:template>
<xsl:template match="persauthorfull">
  <xsl:value-of select="."/>
  <xsl:if test="position()!=last()"><xsl:text>;</xsl:text></xsl:if>
</xsl:template>
</xsl:stylesheet>  

输出:

<?xml version="1.0" encoding="UTF-8"?>
<PA>Lykins, Amy D.;Cantor, James M.;Blanchard, Ray</PA>

“可以调整”我的意思是 - 例如可以省略XML名称空间声明,但也许你想保留它。我想您可能希望稍后从输入中添加更多信息,这可以很容易地扩展模板 如果您是XSLT的新手,就像它的工作原理一样简短 - <xsl:template match="/*">匹配来自root的整个输入XML。然后<xsl:apply-templates select="persauthorfull"/>仅将模板应用于名为persauthorfull的节点。由于有一个模板匹配这些节点 - <xsl:template match="persauthorfull">,因此在那里处理节点。将省略所有其他节点。并且<xsl:if test="position()!=last()"><xsl:text>;</xsl:text></xsl:if>;不是position()时,会在每个节点值之后添加last()