XSLT循环遍历全局配置列表指示的属性

时间:2012-08-04 22:55:45

标签: xslt

全局变量表示,对于各种元素,需要处理哪些属性。

<xsl:variable name="attributes.rtf">
  <element name="measure">
    <att>type</att>
    <att>quantity</att>
    <att>unit</att>
  </element>
  <element name="milestone">
    <att>n</att>
  </element>
  <element name="lb">
    <att>ed</att>
    <att>type</att>
    <att>subtype</att>
    <att>n</att>
  </element>
</xsl:variable>
<xsl:variable name="attributes" select="exslt:node-set($attributes.rtf)" /> <!-- This is XSLT 1.0 -->

当上下文是一个元素时,我需要一个for-each,它将遍历那种元素的属性。我没有看到如何在一个XPath表达式中执行此操作。现在我有这两个:

 <xsl:variable name="temp" select="." />                            <!-- For, say, a <measure> element, -->
 <xsl:for-each select="$attributes/element[@name=name($temp)]/att"> <!-- loop through the names "type", "quantity", and "unit" -->
      <xsl:for-each select="$temp/@*[name()=current()]">            <!-- If an attribute of that name exists in the current <measure> element  -->
                                                                    <!-- (now stored as $temp), then process that attribute. --> 
      </xsl:for-each>
 </xsl:for-each>

有没有办法在一个表达式中执行此操作,而无需创建$ temp。

但是,我还需要一个外部测试条件,指示上下文元素是否具有任何列出的属性。对于那个测试,我想要一个表达式。

(属性的处理确实需要排序,所以可能需要两个循环。但是顺序与测试条件无关。所以也许只需要用一个表达式完成。)

1 个答案:

答案 0 :(得分:2)

<强>予。 “简单”问题:

When the context is an element, I need a for-each that will loop through attributes for that kind of element.

不需要xsl-for-each

I don't see how to do this in one XPath expression.

只需使用

<xsl:apply-templates select=
  "@*[name()=$attributes/element[@name=name(current())]/att]"/>

<强>解释

正确使用 current() 功能。


<强> II。 “复杂”问题:

Processing of the attributes does need to be ordered, so maybe that requires the two loops

以下是一个完整示例,显示没有其他嵌套 <xsl:apply-templates> 是必要的,以按{{1}中指定的顺序生成属性}

$attributes

在以下XML文档中应用此转换时(没有提供!!!):

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

    <xsl:variable name="attributes.rtf">
        <element name="measure">
            <att>type</att>
            <att>quantity</att>
            <att>unit</att>
        </element>
        <element name="milestone">
            <att>n</att>
        </element>
        <element name="lb">
            <att>ed</att>
            <att>type</att>
            <att>subtype</att>
            <att>n</att>
        </element>
    </xsl:variable>

    <xsl:variable name="attributes" select="exslt:node-set($attributes.rtf)" />

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="t/*">
  <xsl:copy>
      <xsl:apply-templates select="$attributes/element[@name=name(current())]/att">
        <xsl:with-param name="pCurrent" select="current()"/>
      </xsl:apply-templates>
      <xsl:apply-templates select=
       "@*[not(name() = $attributes/element[@name=name(current())]/att)]"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="att">
   <xsl:param name="pCurrent" select="/.."/>

  <xsl:if test="$pCurrent[@*[name()=current()]]">
      <xsl:attribute name="{.}">
       <xsl:value-of select="concat(.,'-',.)"/>
      </xsl:attribute>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

产生了想要的正确结果

<t>
  <lb type="normal" ed="uni" n="3"
      subtype="initial" other="yes"/>
  <milestone n="2" other="yes"/>
  <measure quantity="3" unit="cm"
           type="length" other="yes"/>
</t>