【问题标题】:Split one attribute in XML file into two attributes using XSLT使用 XSLT 将 XML 文件中的一个属性拆分为两个属性
【发布时间】:2013-05-28 07:55:59
【问题描述】:

我是 XML/XSLT 的新手。

我需要转换一个包含如下元素的 xml 文件:

<person name="John Smith" />
<person name="Mary Ann Smith" />

变成这样:

<person firstname="John" lastname="Smith" />
<person firstname="Mary Ann" lastname="Smith" />

name 属性可以包含可变数量的单词,只有最后一个应该到 lastname,其余的到 firstname

我正在尝试在 Linux 上使用 XSLT 和 xsltproc 来实现这一点,但欢迎使用任何其他简单的解决方案。

谢谢, 布鲁诺

【问题讨论】:

    标签: xml xslt split


    【解决方案1】:

    XSLT 1.0(以及因此的 XPath 1.0)在其字符串操作功能方面有些限制。有 substring-beforesubstring-after 函数允许您在特定模式的 first 出现之前和之后提取给定字符串的子字符串,但是没有直接的方法可以在最后次出现。您必须使用(尾)递归模板

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:template match="@*|node()">
        <xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
      </xsl:template>
    
      <xsl:template match="person/@name">
        <xsl:call-template name="splitName"/>
      </xsl:template>
    
      <xsl:template name="splitName">
        <!-- start with nothing in $first and all the words in $rest -->
        <xsl:param name="first" select="''" />
        <xsl:param name="rest" select="." />
    
        <xsl:choose>
          <!-- if rest contains more than one word -->
          <xsl:when test="substring-after($rest, ' ')">
            <xsl:call-template name="splitName">
              <!-- move the first word of $rest to the end of $first and recurse.
                   For the very first word this will add a stray leading space
                   to $first, which we will clean up later. -->
              <xsl:with-param name="first" select="concat($first, ' ',
                                                   substring-before($rest, ' '))" />
              <xsl:with-param name="rest" select="substring-after($rest, ' ')" />
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <!-- $rest is now just the last word of the original name, and $first
                 contains all the others plus a leading space that we have to
                 remove -->
            <xsl:attribute name="firstname">
              <xsl:value-of select="substring($first, 2)" />
            </xsl:attribute>
            <xsl:attribute name="lastname">
              <xsl:value-of select="$rest" />
            </xsl:attribute>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
    </xsl:stylesheet>
    

    例子:

    $ cat names.xml
    <people>
      <person name="John Smith" />
      <person name="Mary Ann Smith" />
    </people>
    $ xsltproc split-names.xsl names.xml
    <?xml version="1.0"?>
    <people>
      <person firstname="John" lastname="Smith"/>
      <person firstname="Mary Ann" lastname="Smith"/>
    </people>
    

    如果您不想要 &lt;?xml...?&gt; 行,请添加

    <xsl:output method="xml" omit-xml-declaration="yes" />
    

    到样式表的顶部,紧跟在开头的&lt;xsl:stylesheet&gt; 标记之后。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-14
      • 1970-01-01
      • 1970-01-01
      • 2021-06-17
      • 2012-07-29
      • 2012-08-23
      • 1970-01-01
      • 2021-03-26
      相关资源
      最近更新 更多