使用xslt从XML的多个属性值中获取单个值

时间:2012-02-17 11:19:51

标签: xml xslt

我有一个xml,我想要使用XSL文件在“标题”中定义的属性。我想检索样式的值“abc”和“cdf”值

<catalog>
    <cd>
       <title style="abc:true;cdf:false"  att2="false">Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
</catalog>

我试过这个

 <td><xsl:value-of select="substring-before(substring-after(@style,'abc:'),';')"/></td>

3 个答案:

答案 0 :(得分:3)

这是一个通用转换,允许处理包含无限数量的名称 - 值对的字符串

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <xsl:variable name="vStyle" select="/*/*/title/@style"/>

  The value for 'abc' is : <xsl:text/>
  <xsl:call-template name="getValueOfName">
   <xsl:with-param name="pText" select="$vStyle"/>
   <xsl:with-param name="pName" select="'abc'"/>
  </xsl:call-template>

  The value for 'cdf' is : <xsl:text/>
  <xsl:call-template name="getValueOfName">
   <xsl:with-param name="pText" select="$vStyle"/>
   <xsl:with-param name="pName" select="'cdf'"/>
  </xsl:call-template>


  The value for 'xyz' is : <xsl:text/>
  <xsl:call-template name="getValueOfName">
   <xsl:with-param name="pText" select="$vStyle"/>
   <xsl:with-param name="pName" select="'xyz'"/>
  </xsl:call-template>
 </xsl:template>

 <xsl:template name="getValueOfName">
  <xsl:param name="pText"/>
  <xsl:param name="pName"/>

  <xsl:choose>
      <xsl:when test="not(string-length($pText) > 0)"
        >***Not Found***</xsl:when>
      <xsl:otherwise>
        <xsl:variable name="vPair" select=
         "substring-before(concat($pText, ';'), ';')"/>

         <xsl:choose>
           <xsl:when test=
           "$pName = substring-before(concat($vPair, ':'), ':')">

             <xsl:value-of select="substring-after($vPair, ':')"/>
           </xsl:when>
           <xsl:otherwise>
             <xsl:call-template name="getValueOfName">
               <xsl:with-param name="pText" select=
                  "substring-after($pText, ';')"/>
               <xsl:with-param name="pName" select="$pName"/>
             </xsl:call-template>
           </xsl:otherwise>
         </xsl:choose>
      </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<catalog>
    <cd>
        <title style="abc:true;cdf:false"  att2="false">Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
</catalog>

产生想要的结果

  The value for 'abc' is : true

  The value for 'cdf' is : false


  The value for 'xyz' is : ***Not Found***

<强>解释

getValueOfName模板是一个通用模板,用于查找包含指定pName的名称 - 值对,然后输出值 - 或者如果根本找不到此名称,则为***Not Found***模板输出{1}}。

模板首先从字符串中获取第一个名称 - 值对并对其进行处理。如果当前名称 - 值对中不存在pName,则模板会在当前名称 - 值对之后的文本上递归调用自身。

答案 1 :(得分:2)

我怀疑您的问题与您引用@style属性的方式有关。

如果您使用的是XPath 2.0,则可以在/运算符的右侧使用函数调用(例如substring-after,substring-before)。所以这将有效:

/catalog/cd/title/substring-before(substring-after(@style,'abc:'),';')

在XPath 1.0中,你不能这样做,每个/右边的东西必须是一个轴步(不是函数调用),所以你必须使用:

substring-before(substring-after(/catalog/cd/title/@style,'abc:'),';') 

答案 2 :(得分:1)

我认为你很亲密:

  <!-- abc -->
  <xsl:value-of 
       select="substring-after(
               substring-before(/catalog/cd/title/@style,';'),'abc:')"/>
  <!-- cdf -->
 <xsl:value-of 
      select="substring-after(
              substring-after(/catalog/cd/title/@style,';'),'cdf:')"/>