Create list of nodes by copying from another lists

北慕城南 提交于 2019-12-11 20:21:01

问题


I have a XSLT template where I need to merge two lists of nodes conditionally. I have the following two XML fragments:

<vo>
    <field name="userLoginName"       nameLDAP="uid"              type="String"/>
    <field name="displayName"         nameLDAP="displayName"      type="String"/>
    <field name="firstName"           nameLDAP="givenName"        type="String"/>
    <field name="lastName"            nameLDAP="sn"               type="String"/>
    <field name="mail"                nameLDAP="mail"             type="String"/>
    <field name="userPassword"        nameLDAP="userPassword"     type="String" hidden="true"/>
    <field name="center"              nameLDAP="center"           type="String"/>
</vo>

<input>
    <field name="userPassword"/>
    <field name="oldPasswordInQuotes" nameLDAP="unicodePwd"       type="byte[]"/>        
</input>

I want to create a xml fragment that will have the same nodeas as input/field. For each one of those nodes I want to check if there is a node with the same name in the list vo/field. If there is, then it should be copied to the new list. Otherwise, it should copy the same node we are iterating over. In this case the output should be something like this:

<field name="userPassword"        nameLDAP="userPassword"     type="String" hidden="true"/>
<field name="oldPasswordInQuotes" nameLDAP="unicodePwd"       type="String"/>        

So far I've the following transformation:

    <xsl:variable name="fields" select="vo/field" />

    <xsl:variable name='allParameters'>
        <xsl:for-each select="input/field">
            <xsl:variable name="inputFieldName" select="@name"/>
            <xsl:choose>
                <xsl:when test="$fields[@name = $inputFieldName]">
                    <xsl:copy-of select="$fields[@name = $inputFieldName]"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="."/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:variable>

    <xsl:message>Parameters <xsl:copy-of select="$allParameters" /> </xsl:message>

    <xsl:for-each select="$allParameters">
        <xsl:message>Parameter <xsl:value-of select="@name" /> found !!! </xsl:message>
    </xsl:for-each>

The output is

Parameters <field name="userPassword" nameLDAP="userPassword" type="String" hidden="true"/><field name="oldPasswordInQuotes" nameLDAP="unicodePwd" type="byte[]"/>
Parameter  found !!!

The first xsl:message seems to show that the copy worked fine, but when I try to iterate over it, it is obviously not working(there is only one message "Parameter found" and it is not showing the parameter name). What am I missing?


回答1:


I think you want something like:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:key name="vo" match="vo/field" use="@name" />

<xsl:template match="/">
    <xsl:for-each select="root/input/field">
        <xsl:choose>
            <xsl:when test="key('vo', @name)">
                <xsl:copy-of select="key('vo', @name)"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy-of select="."/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Applied to a wel-formed input:

<root>
    <vo>
        <field name="userLoginName"       nameLDAP="uid"              type="String"/>
        <field name="displayName"         nameLDAP="displayName"      type="String"/>
        <field name="firstName"           nameLDAP="givenName"        type="String"/>
        <field name="lastName"            nameLDAP="sn"               type="String"/>
        <field name="mail"                nameLDAP="mail"             type="String"/>
        <field name="userPassword"        nameLDAP="userPassword"     type="String" hidden="true"/>
        <field name="center"              nameLDAP="center"           type="String"/>
    </vo>
    <input>
        <field name="userPassword"/>
        <field name="oldPasswordInQuotes" nameLDAP="unicodePwd"       type="byte[]"/>        
    </input>
</root>

results in:

<field name="userPassword" nameLDAP="userPassword" type="String" hidden="true"/>
<field name="oldPasswordInQuotes" nameLDAP="unicodePwd" type="byte[]"/>

Edit:

To answer your question regarding the number of messages in your test: there is only one $allParameters node; to iterate over its inner nodes (assuming XSLT 2.0), try:

<xsl:for-each select="$allParameters/field">
    <!-- your code here -->
</xsl:for-each>


来源:https://stackoverflow.com/questions/26836469/create-list-of-nodes-by-copying-from-another-lists

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!