2

全局变量为各种元素中的每一种指示需要处理哪些属性。

<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.

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

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

4

1 回答 1

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()功能。


二、“复杂”的问题

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

这是一个完整的示例,显示无需其他嵌套 即可按中指定的顺序生成属性:<xsl:apply-templates> $attributes

<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>

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

<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>

产生了想要的正确结果

<t>
   <lb ed="ed-ed" type="type-type" subtype="subtype-subtype" n="n-n" other="yes"/>
   <milestone n="n-n" other="yes"/>
   <measure type="type-type" quantity="quantity-quantity" unit="unit-unit" other="yes"/>
</t>
于 2012-08-04T23:30:52.337 回答