在具有相同名称的元素文本之间插入空格

时间:2012-04-29 16:34:28

标签: xml xslt transformation

对于精通XSLT的作者来说,回答这个问题可能相当简单。

我有以下示例XML文档:

<?xml version="1.0" encoding="UTF-8"?>
<students>
    <student num="12345678">
        <name>Dona Diller</name>
        <dob>1970-07-21</dob>
        <education>BSc</education>
        <education>MSc</education>
        <status>Married</status>
    </student>

<!-- more student elements to follow... -->

</students>

以下XSL:

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

    <xsl:template match="/">
        <html>
            <title>Test</title>
            <body>
                <h1>Personal details</h1>
                <xsl:apply-templates select="students/student"/>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="student">
        <p>
            Student number:
            <xsl:value-of select="@num"/>
        </p>
        <p>Full name:
            <xsl:value-of select="name"/>
        </p>
        <p>Date of birth
            <xsl:value-of select="dob"/>
        </p>
        <!-- TODO: text of 'education' elements must be separated by a space -->
        <p>Degrees:
            <xsl:apply-templates select="education"/>
        </p>
        <p>Status:
            <xsl:value-of select="status"/>
        </p>
    </xsl:template>

</xsl:stylesheet>

当应用于本文开头所包含的XML文档时,会产生以下XHTML输出:

<html>
   <title>Test</title>
   <body>
      <h1>Personal details</h1>
      <p>
         Student number:
         12345678
      </p>
      <p>Full name:
         Dona Diller
      </p>
      <p>Date of birth
         1970-07-21
      </p>
      <p>Degrees:
         BScMSc
      </p>
      <p>Status:
         Married
      </p>
   </body>
</html>

我的问题是学位名称合并为一个字符串(教育元素的文本)。因此,而不是获得BScMSc&#39;在输出中,我想显示BSc MSc&#39;在前面的例子中。有什么想法吗?

4 个答案:

答案 0 :(得分:4)

Novatchev和Honnen的解决方案都会起作用(当然),但对他们来说有点不满意。我想如果你要将教育元素的格式委托给模板规则,那么该模板规则应该只关注一个教育元素的格式,而不是一组相邻元素的格式。对我来说,插页式间距恰好是父模板的工作。所以我想我会倾向于写:

<xsl:for-each select="education">
  <xsl:if test="position() ne 1"><xsl:text> </xsl:text></xsl:if>
  <xsl:apply-templates select="."/>
</xsl:for-each>

但这是一个意见问题。

答案 1 :(得分:2)

添加模板

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

答案 2 :(得分:1)

<强>更短的/简单的/更可读

添加此模板

<xsl:template match="education[position() > 1]">
  <xsl:value-of select="concat(' ', .)"/>
</xsl:template>

答案 3 :(得分:0)

只需在每个学位的末尾添加一个空格:

<xsl:template match="education">
    <xsl:value-of select="concat(.,' ')"/>
</xsl:template>

是的,这会在度数列表的末尾产生一个无关的空间,但在这种情况下这不是问题。

如果您有XSLT 2.0,可以尝试

<p>Degrees:
    <xsl:value-of select="string-join(education,' ')"/>
</p>