在foreach中使用嵌套键

时间:2016-09-05 07:21:21

标签: xml xslt xslt-1.0

我想实现双重查找功能,

我需要将<Node2>内的<Product>元素的值设置为外部xml的值 与此xml的关系是通过<lookup>

的值<ID>元素
<?xml version="1.0" encoding="utf-8"?>
<Products>
    <lookup>
        <Ref>
            <ID>1</ID>
            <outer_id>110</outer_id>
        </Ref>
        <Ref>
            <ID>2</ID>
            <outer_id>220</outer_id>
        </Ref>
    </lookup>   
    <Product>
        <item>
         <ID>1</ID>
         <Node2>A</Node2>
        </item> 
        <item>
         <ID>2</ID>
         <Node2>B</Node2>
        </item>             
    </Product>  
</Products>


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

    <xsl:param name="f1" select="'xml2.xml'"/>
    <xsl:variable name="doc1" select="document($f1)"/>

    <xsl:key name="k1" match="Products/Product" use="@prodId"/>

    <xsl:key name="look" match="Products/lookup/Ref/outer_id" use="../ID"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>


    <xsl:template match="Products/Product/item/Node2">

        <xsl:variable name="cur" select="current()"/>
        <xsl:copy>
            <xsl:choose>
                <xsl:when test="key('look', normalize-space(normalize-space($cur/../ID)))">                 
                    <xsl:for-each select="$doc1">
                        <xsl:value-of select="key('k1', key('look', normalize-space(normalize-space($cur/../ID))))/@myvalue"/>
                    </xsl:for-each>
                </xsl:when>
            </xsl:choose>
        </xsl:copy>

    </xsl:template>
</xsl:stylesheet>

它看起来像一个不是很复杂的任务,但它对我不起作用,我想由于我的'上下文'在foreach内发生了变化,因此无法使用'look'键

请提出解决方案。

1 个答案:

答案 0 :(得分:0)

问题确实是上下文之一,在<xsl:for-each select="$doc1">语句中,key('look', ...)的任何使用都将在$doc1的上下文中,而不是原始的XML文档。

在这种情况下,解决方案只是评估密钥并将结果放在xsl:for-each之前的变量中,并在内部使用变量。

<xsl:template match="Products/Product/item/Node2">
    <xsl:variable name="cur" select="current()"/>
    <xsl:copy>
        <xsl:variable name="look" select="key('look', normalize-space(normalize-space($cur/../ID)))" />
        <xsl:choose>
            <xsl:when test="$look">                 
                <xsl:for-each select="$doc1">
                    <xsl:value-of select="key('k1', $look)/@myvalue"/>
                </xsl:for-each>
            </xsl:when>
        </xsl:choose>
    </xsl:copy>
</xsl:template>