简体   繁体   English

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

[英]Looping through all attributes of a XML element in XSLT

I am trying to use <xsl:for-each select="@*"> to grab all the attributes of a given element but when i do that my <xsl:choose> statement doesn't execute. 我试图使用<xsl:for-each select="@*">来获取给定元素的所有属性,但是当我这样做时,我的<xsl:choose>语句无法执行。

Here is the element that I'm working with: 这是我正在使用的元素:
<textBox id="Airfare" value="" label="text 1"/>

Here is the XSLT template I'm using: 这是我正在使用的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>

And when I generate the HTML using PHP I get this: 当我使用PHP生成HTML时,我得到以下信息:

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

As you can see it didn't add form_ to the id attribute it didn't generate a name attribute and it didn't skip over the label attribute. 如您所见,它没有将form_添加到id属性中,没有生成name属性,也没有跳过label属性。

 <xsl:element name="input"> <xsl:attribute name="type">text</xsl:attribute> <xsl:for-each select="@*"> <xsl:choose> <xsl:when test="@id"> 

This tests if the current node (an attribute) has an attribute named id . 这将测试当前节点(一个属性)是否具有名为id的属性。 Because an attribute cannot have atributes itself, the test will never succeed. 因为属性本​​身不能具有属性,所以测试将永远不会成功。

Here is a concise XSLT solution using templates, no <xsl:for-each> and no conditional logic : 这是一个使用模板的简洁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>

when this transformation is applied on the given XML document : 当此转换应用于给定的XML文档时

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

the desired, correct result is produced : 产生所需的正确结果

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

when applied on this XML document (missing label attribute): 应用于此XML文档时 (缺少label属性):

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

the correct result is produced : 产生正确的结果

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

Hi you have made 2 mistakes: 嗨,您犯了2个错误:

  1. testing if current attribute is wrong.The correct(in my opinion of course) is: name() = 'id' 测试当前属性是否错误。正确(我认为当然)是:name()='id'
  2. Selecting the value of current attribute should be selected using'.' 选择当前属性的值应使用“。”来选择。

Basically in the body of the for-each loop your current element is an attribute. 基本上在for-each循环的主体中,当前元素是一个属性。 Which is a pair name and value. 这是一对名称和值。 so using name() gives you the name and the value is selected by default. 因此使用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>

I suggest you change testing conditions for the others test clauses. 我建议您更改其他测试条款的测试条件。

PS It depends on your xsl transformations but you would probably want to remove white spaces in creation of the new html attributes for example this one: PS这取决于您的xsl转换,但是您可能希望在创建新的html属性时删除空格,例如以下示例:

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

have to be: 不得不:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM