首页 > 解决方案 > XSLT - 如何根据分隔符拆分字符串并将值分配给多个属性

问题描述

输入 XML:

<testng-results>
<suite>
    <test>
        <class>
            <test-method status="PASS" description="Test_ID:123,Test_Name:Test ABC,Product:Product ABC"></test-method>
            <test-method status="PASS" description="Test_ID:456,Test_Name:Test XYZ,Product:Product XYZ"></test-method>
        </class>
    </test>
</suite>
</testng-results>

我当前的 XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:template match="/">
  <Suite>
     <xsl:for-each select="testng-results/suite/test/class/test-method">
        <test>
           <xsl:attribute name="status">
              <xsl:value-of select="@status" />
           </xsl:attribute>
           <xsl:attribute name="Test_ID">
              <xsl:value-of select="" />
           </xsl:attribute>
           <xsl:attribute name="Test_Name">
              <xsl:value-of select="" />
           </xsl:attribute>
           <xsl:attribute name="Product">
              <xsl:value-of select="" />
           </xsl:attribute>
        </test>
     </xsl:for-each>
  </Suite>

预期输出.XML:

<?xml version="1.0" encoding="UTF-8"?>
<Suite>
   <test status="PASS" Test_ID="123" Test_Name="Test ABC" Product="Product ABC" />
   <test status="PASS" Test_ID="456" Test_Name="Test XYZ" Product="Product XYZ" />
</Suite>

我必须从“描述”值中获取字符串并拆分这些值以生成输出 xml。

我读过 XSLT 2.0 更好地配备了字符串标记化功能。但是,我只能使用 XSLT 1.0。

标签: xmlxsltsplitxslt-1.0

解决方案


我提出这种方法。它相当粗糙,但可以肯定,因为它仅依赖于标准 XSLT 元素和函数:

(为了标记化,它实现了一个递归算法。)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="xml" version="1.0" indent="yes"/>

<xsl:template match="/">
    <Suite>
        <xsl:apply-templates select="testng-results/suite/test/class/test-method"></xsl:apply-templates>
    </Suite>
</xsl:template>

<xsl:template match="test-method">
    <test>
        <xsl:call-template name="tokenize-to-attrs">
            <xsl:with-param name="s" select="@description"/>
        </xsl:call-template>
    </test> 
</xsl:template>

<xsl:template name="tokenize-to-attrs">
    <xsl:param name="s"/>
    <xsl:variable name="pair" select="substring-before($s, ',')"/>
    <xsl:if test="$pair">
        <xsl:call-template name="to-attr">
            <xsl:with-param name="s" select="$pair"/>
        </xsl:call-template>
        <xsl:call-template name="tokenize-to-attrs">
            <xsl:with-param name="s" select="substring-after($s, ',')"/>
        </xsl:call-template>
    </xsl:if>
    <xsl:if test="not($pair)">
        <xsl:call-template name="to-attr">
            <xsl:with-param name="s" select="$s"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

<xsl:template name="to-attr">
    <xsl:param name="s"/>
    <xsl:variable name="name" select="substring-before($s, ':')"/>
    <xsl:variable name="value" select="substring-after($s, ':')"/>
    <xsl:attribute name="{$name}">
        <xsl:value-of select="$value"/>
    </xsl:attribute>
</xsl:template>

</xsl:stylesheet>

推荐阅读