XSLT - 提取所有文本但最后一小节

时间:2016-06-02 20:40:11

标签: xslt

希望从xml中的完整类名解析出命名空间。

数据示例:

<results>
    <test-case name="Co.Module.Class.X">
</results>

最终结果(转到csv格式): ,Co.Module.Class

样式表:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
  <xsl:output method="text" indent="yes" encoding="ISO-8859-1"/>
  <xsl:param name="delim" select="','" />
  <xsl:param name="quote" select="'&quot;'" />
  <xsl:param name="break" select="'&#xA;'" />
  <xsl:template match="/">
FullTestName, Namespace
<xsl:apply-templates select="//test-case" />
  </xsl:template>

  <xsl:template match="test-case">
    <xsl:apply-templates />
      <xsl:value-of select="@name" />
      <xsl:value-of select="$delim" />
      <xsl:value-of select="function to go here for nameWithJustNamespace" />
      <xsl:value-of select="$break" />    
  </xsl:template>

我理解这个过程需要最后一个索引&#34;。&#34;被叫一次,但我没有找到XSLT来拥有这个功能。如何最好地完成这个?

2 个答案:

答案 0 :(得分:0)

要在纯XSLT 1.0中执行此操作,您需要调用命名的递归模板,例如:

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="/results">
    <xsl:call-template name="remove-last-token">
        <xsl:with-param name="text" select="test-case/@name"/>
    </xsl:call-template>
</xsl:template>

<xsl:template name="remove-last-token">
    <xsl:param name="text"/>
    <xsl:param name="delimiter" select="'.'"/>
    <xsl:value-of select="substring-before($text, $delimiter)"/>
    <xsl:if test="contains(substring-after($text, $delimiter), $delimiter)">
        <xsl:value-of select="$delimiter"/>
        <xsl:call-template name="remove-last-token">
            <xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

这个纯XSLT 1.0转换(更短,没有条件XSLT操作,单个模板):

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

  <xsl:template match="test-case[contains(@name, '.')]">
  <xsl:param name="pDotIndex" select="0"/>

   <xsl:variable name="vNextToken" 
        select="substring-before(substring(@name, $pDotIndex+1), '.')"/>
   <xsl:value-of select="concat(substring('.', 2 - ($pDotIndex > 0)),$vNextToken)"/>
   <xsl:variable name="vNewDotIndex" select="$pDotIndex+string-length($vNextToken)+1"/>
   <xsl:apply-templates 
        select="self::node()[contains(substring(@name,$vNewDotIndex+1), '.')]">
     <xsl:with-param name="pDotIndex" select="$vNewDotIndex"/>
   </xsl:apply-templates>
  </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<results>
    <test-case name="Co.Module.Class.X"/>
</results>

生成想要的正确结果

Co.Module.Class

第2部分

稍作修改后,以下转换将生成完整的CSV:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

  <xsl:template match="test-case[contains(@name, '.')]">
  <xsl:param name="pDotIndex" select="0"/>

   <xsl:variable name="vNextToken" 
        select="substring-before(substring(@name, $pDotIndex+1), '.')"/>
   <xsl:value-of select="concat(substring(',', 2 - (position() > 1)),
                                substring('.', 2 - ($pDotIndex > 0)),  $vNextToken)"/>
   <xsl:variable name="vNewDotIndex" select="$pDotIndex+string-length($vNextToken)+1"/>
   <xsl:apply-templates 
        select="self::node()[contains(substring(@name,$vNewDotIndex+1), '.')]">
     <xsl:with-param name="pDotIndex" select="$vNewDotIndex"/>
   </xsl:apply-templates>
  </xsl:template>
</xsl:stylesheet>

应用于此XML文档

<results>
    <test-case name="Co.Module.Class.X"/>
    <test-case name="Co2.Module2.Class2.Y"/>
    <test-case name="Co3.Module3.Class3.Z"/>
</results>

生成了需要的,正确的(CSV)结果

Co.Module.Class,Co2.Module2.Class2,Co3.Module3.Class3