循环遍历XSLT中XML元素的所有属性

时间:2010-06-17 13:51:05

标签: php html xml xslt

我正在尝试使用<xsl:for-each select="@*">来获取给定元素的所有属性,但是当我这样做时,我的<xsl:choose>语句不会执行。

这是我正在使用的元素:
<textBox id="Airfare" value="" label="text 1"/>

这是我正在使用的XSLT模板:

<xsl:template match="textBox">
<div>
    <xsl:choose>
        <xsl:when test="@label">
            <xsl:value-of select="@label"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>No Label Defined</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
<xsl:element name="input">
    <xsl:attribute name="type">text</xsl:attribute>
    <xsl:for-each select="@*">
        <xsl:choose>
            <xsl:when test="@id">
                <xsl:attribute name="name">form_<xsl:value-of select="@id"/></xsl:attribute>
                <xsl:attribute name="id">form_<xsl:value-of select="@id"/></xsl:attribute>
            </xsl:when>
            <xsl:when test="@label">
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy-of select="current()"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:for-each>
</xsl:element>
</div>

当我使用PHP生成HTML时,我得到了这个:

<div>text 1<input type="text" id="Airfare" value="" label="text 1"></div>

正如您所看到的,它没有将form_添加到id属性,它没有生成name属性,也没有跳过label属性。

2 个答案:

答案 0 :(得分:2)

<xsl:element name="input">       
    <xsl:attribute name="type">text</xsl:attribute>      

    <xsl:for-each select="@*">       
        <xsl:choose>       
            <xsl:when test="@id">

这将测试当前节点(属性)是否具有名为id的属性。由于属性本身不具有属性,因此测试永远不会成功。

这是一个使用模板的简洁XSLT解决方案,没有<xsl:for-each>且没有条件逻辑

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" exclude-result-prefixes="my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vNoLabelVal" select="'No Label Defined'"/>

 <xsl:template match="textBox">
  <xsl:value-of select="concat(@label, substring($vNoLabelVal, 1 div not(@label)))"/>
  <input type="text">
    <xsl:apply-templates select="@*"/>
  </input>
 </xsl:template>

 <xsl:template match="textBox/@*">
  <xsl:copy-of select="."/>
 </xsl:template>

 <xsl:template match="textBox/@id">
  <xsl:attribute name="name">
   <xsl:value-of select="concat('form_', .)"/>
  </xsl:attribute>
 </xsl:template>

 <xsl:template match="textBox/@label"/>
</xsl:stylesheet>

将此转换应用于给定的XML文档

<textBox id="Airfare" value="" label="text 1"/>

产生了所需的正确结果

text 1<input type="text" name="form_Airfare" value="" />

应用于此XML文档(缺少label属性)时:

<textBox id="Airfare" value="" />

产生了正确的结果

No Label Defined<input type="text" name="form_Airfare" value="" />

答案 1 :(得分:1)

你好,你犯了两个错误:

  1. 测试当前属性是否错误。正确(我认为当然)是:name()='id'
  2. 应使用'。'
  3. 选择当前属性的值

    基本上在for-each循环的主体中,当前元素是一个属性。这是一对名称和价值。所以使用name()为您提供名称,默认选择值。

     <xsl:template match="textBox">
        <div>
          <xsl:choose>
            <xsl:when test="@label">
              <xsl:value-of select="@label"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:text>No Label Defined</xsl:text>
            </xsl:otherwise>
          </xsl:choose>
          <xsl:element name="input">
            <xsl:attribute name="type">text</xsl:attribute>
            <xsl:for-each select="@*">
              <xsl:choose>
                <xsl:when test="name() = 'id'">
                  <xsl:attribute name="name">form_<xsl:value-of select="."/>
                  </xsl:attribute>
                  <xsl:attribute name="id">form_<xsl:value-of select="."/>
                  </xsl:attribute>
                </xsl:when>
                <xsl:when test="@label">
                </xsl:when>
                <xsl:otherwise>
                  <xsl:copy-of select="current()"/>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:for-each>
          </xsl:element>
        </div>
      </xsl:template>
    

    我建议您更改其他测试条款的测试条件。

    P.S这取决于你的xsl转换,但你可能想要在创建新的html属性时删除空格,例如这个:

          <xsl:attribute name="id">
            form_<xsl:value-of select="."/>
          </xsl:attribute>
    

    必须是:

    <xsl:attribute name="name">form_<xsl:value-of select="."/>