在xpath表达式中使用name()来匹配具有未知节点名称的节点

时间:2016-02-17 11:28:53

标签: xml xslt xpath

我在xsl文档中遇到以下测试(xpath)时出现问题:

<xsl:if test="document('../resourcefiles/users.xml')/users/user[email=$email]/*[name()= current()/../../@id] = current()/@value">
    <xsl:attribute selected="true"></xsl:attribute>
</xsl:if>

xsl文档(下面)正在构建一个表单,其中包含在一个xml文档(registry.xml)中定义的表单元素,用另一个xml文档(users.xml)中的某个用户的数据填充表单元素。 'registry.xml'可能会发生变化,因此不知道表单将包含哪些元素,只是它们将遵循与当前registry.xml中相同的结构。除了一种类型的表单元素之外,这种方式很有效:“select”类型的表单元素。上面的测试应该从users.xml中选择用户,电子邮件等于$ email( / users / user [email = $ email] ),然后匹配保存的属性值user.xml中的user,其中包含从registry.xml获取的正确选项值(/ users / user [email = $ email] / * [name()= current()/../../@ id] =电流()/ @值)。当测试为真时,xsl会向相关选项添加一个属性(selected =“true”)。

我认为我在xpath测试中做错了什么,但我无法绕过它。

xml文档是 registry.xml (其中找到了'users'及其属性结构的信息):

<?xml version="1.0" encoding="UTF-8"?>
<registry>
   <objects>
    <user created="dd.mm.yy" lastactive="dd.mm.yy" status="1">
        <attribute>
            <name>created</name>
        </attribute>
        <attribute>
            <name>lastactive</name>
        </attribute>
        <attribute>
            <name>status</name>
        </attribute>
        <property type="checkbox" id="administrator" status="99" mandatory="false" securitysetting="99" sortorder="6" unique="false">
            <name>Site Administrator</name>
        </property>
        <property type="text" id="name" status="1" mandatory="true" securitysetting="1" sortorder="0" unique="false">
            <name>Full Name</name>
        </property>
        <property type="email" id="email" status="1" mandatory="true" securitysetting="1" sortorder="1" unique="true">
            <name>Email</name>
        </property>
        <property type="text" id="password" status="1" mandatory="true" securitysetting="1" sortorder="2" unique="false">
            <name>Password</name>
        </property>
        <property type="select" id="animal" status="1" securitysetting="99" mandatory="false" sortorder="5" unique="false">
            <name>Animal</name>
            <options>
                <option value="monkey">Monkey</option>
                <option value="horse">Horse</option>
                <option value="lion">Lion</option>
            </options>
        </property>
        <property type="text" id="phone" status="1" securitysetting="1" mandatory="false" sortorder="3" unique="false">
            <name>Phone</name>
            <options/>
        </property>
        <property type="checkbox" id="checkbox" status="1" securitysetting="1" mandatory="false" sortorder="4" unique="false">
            <name>Checkbox</name>
            <options/>
        </property>
    </user>
   </objects>
</registry>

users.xml

<?xml version="1.0"?>
<users>
 <user created="14.02.16" lastactive="never" status="1">
  <administrator>true</administrator>
  <name>Tom Hanks</name>
  <email>th@aficdd.at</email>
  <password>tham</password>
  <animal>monkey</animal>
  <phone>+43123123</phone>
  <checkbox>false</checkbox>
 </user>
 <user created="15.02.16" lastactive="never" status="1">
  <administrator>false</administrator>
  <name>Navn Navnesen</name>
  <email>asdf@gmail.com</email>
  <password>asdf</password>
  <animal>horse</animal>
  <phone>+43987987</phone>
  <checkbox>true</checkbox>
 </user>
 <user created="16.02.16" lastactive="never" status="0">
  <administrator>false</administrator>
  <name>Deaktiveret Bruger</name>
  <email>deactive@asdfasdf.cs</email>
  <password>deactive</password>
  <animal>lion</animal>
  <phone>+4435345</phone>
  <checkbox>false</checkbox>
 </user>
</users>

xsl文档是:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="email"/>


<xsl:template match="/">

<br/>
<form action="javascript:validateEdituserForm()">
<table>

    <xsl:for-each select="document('../resourcefiles/registry.xml')/registry/objects/user/property[@status != '0']">
        <xsl:sort order="ascending" select="@sortorder"/>

        <tr>
            <td><p class="loginform"><xsl:value-of select="./name"/><xsl:if test="@mandatory = 'true'">*</xsl:if>:</p></td>
            <td>
            <xsl:choose>
                <!-- property is a select element -->
                <xsl:when test="@type = 'select'">
                    <select>
                        <xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
                        <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
                        <xsl:attribute name="class">autoproperty<xsl:if test="@mandatory = 'true'"> mandatory</xsl:if></xsl:attribute>
                        <xsl:attribute name="onchange">javascript:addUserFormChange(this.id);</xsl:attribute>
                        <xsl:for-each select="./options/option">
                            <option>
                                <xsl:attribute name="value"><xsl:value-of select="@value"/></xsl:attribute>
<!-- HERE IS MY PROBLEM -->
                                <xsl:if test="document('../resourcefiles/users.xml')/users/user[email=$email]/*[name()= current()/../../@id] = current()/@value"><xsl:attribute name="selected">true</xsl:attribute></xsl:if>
<!-- ABOVE IS MY PROBLEM -->
                                <xsl:value-of select="name"/>
                            </option>
                        </xsl:for-each>
                    </select>
                </xsl:when>
                <!-- property is a checkbox -->
                <xsl:when test="@type = 'checkbox'">
                    <input>
                        <xsl:attribute name="type"><xsl:value-of select="@type"/></xsl:attribute>
                        <xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
                        <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
                        <xsl:attribute name="class">autoproperty<xsl:if test="@mandatory = 'true'"> mandatory</xsl:if></xsl:attribute>
                        <xsl:attribute name="onkeyup">javascript:addUserFormChange(this.id);</xsl:attribute>
                        <xsl:if test="document('../resourcefiles/users.xml')/users/user[email=$email]/*[name()= current()/@id] = 'true'"><xsl:attribute name="checked">true</xsl:attribute></xsl:if>
                    </input>
                </xsl:when>
                <!-- property is any other type -->
                <xsl:otherwise>
                    <input>
                        <xsl:attribute name="type"><xsl:value-of select="@type"/></xsl:attribute>
                        <xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
                        <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
                        <xsl:attribute name="class">autoproperty<xsl:if test="@mandatory = 'true'"> mandatory</xsl:if></xsl:attribute>
                        <xsl:attribute name="onkeyup">javascript:addUserFormChange(this.id);</xsl:attribute>
                        <xsl:attribute name="value"><xsl:value-of select="document('../resourcefiles/users.xml')/users/user[email=$email]/*[name()= current()/@id]"/></xsl:attribute>
                    </input>
                </xsl:otherwise>
            </xsl:choose>
            </td>
            <td><p class="formalert"><xsl:attribute name="id"><xsl:value-of select="@id"/>alert</xsl:attribute></p></td>
        </tr>
    </xsl:for-each>
 <tr>
  <td><p class="loginform">&#160;</p></td>
  <td></td>
  <td></td>
 </tr>
 <tr>
  <td><p class="loginform">Notify user per email:</p></td>
  <td><input class="autoproperty" type="checkbox" name="notifyuser" id="notifyuser" onclick="javascript:notifyuserclicked();"/></td>
  <td><p class="formalert" id="notifyuseralert"></p></td>
 </tr>
 <tr>
  <td><input type="button" class="button" onclick="javascript:newClearFormElements();"><xsl:attribute name="value"><xsl:value-of select="document('../resourcefiles/lang/labels.xml')/labels/label[@id = 'labelbuttonclearform']/value"/></xsl:attribute></input></td>
  <td><input type="submit" class="button"><xsl:attribute name="value"><xsl:value-of select="document('../resourcefiles/lang/labels.xml')/labels/label[@id = 'labelbuttonsavechanges']/value"/></xsl:attribute></input></td>
 </tr>
</table>
<p class="formalert" id="edituseralertarea"></p>
</form>

</xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:1)

终于找到了。由于我不太明白的原因,xpath测试必须改为:

test="document('../resourcefiles/users.xml')/users/user[email=$email]/*[name()= current()/../../@id] = current()/@value"

成:

test="document('../resourcefiles/users.xml')/users/user[email=$email]/*[name()= current()/../../@id] = @value"

我仍然不知道为什么当前()/ @值不起作用而 @value 确实有效,但它确实有效。