Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
114 views
in Technique[技术] by (71.8m points)

XSLT 1.0: key not working in selecting nodes

I have an XML and an XSLT that gives a current output. It uses a "key" but I am not getting the expected output

Source XML:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <Receivers>
        <ReceiverRule>
            <Condition>
                <Value>Condition 1</Value>
            </Condition>
            <Receiver>
                <party>party1</party>
                <system>SYS1</system>
            </Receiver>
        </ReceiverRule>
        <ReceiverRule>
            <Condition>
                <Value>Condition 2</Value>
            </Condition>
            <Receiver>
                <party>party2</party>
                <system>SYS2</system>
            </Receiver>
        </ReceiverRule>
    </Receivers>
    <ReceiverInterfaces>
        <Receiver>
            <party>party1</party>
            <system>SYS1</system>
        </Receiver>
        <ReceiverInterfaceRule>
            <Rule>Rule 1 sytem 1</Rule>
        </ReceiverInterfaceRule>
        <ReceiverInterfaceRule>
            <Rule>Rule 2 system 1</Rule>
        </ReceiverInterfaceRule>
    </ReceiverInterfaces>
    <ReceiverInterfaces>
        <Receiver>
            <party>party2</party>
            <system>SYS2</system>
        </Receiver>
        <ReceiverInterfaceRule>
            <Rule>Rule 1 system 2</Rule>
        </ReceiverInterfaceRule>
        <ReceiverInterfaceRule>
            <Rule>Rule 2 system 2</Rule>
        </ReceiverInterfaceRule>
    </ReceiverInterfaces>
</Root>

My XSLT:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output indent="yes"/>
    
    <xsl:key name="Receiver" match="ReceiverRule/Receiver" use="concat(party,system)"/>
    
    <xsl:template match="Root">
        <ReceiverList>
            <xsl:apply-templates select="Receivers/ReceiverRule"/>
        </ReceiverList>
    </xsl:template>
    
    <xsl:template match="ReceiverRule">
        <Receiver>
            <Name>
                <xsl:value-of select="concat(Receiver/party, ' ' ,Receiver/system)"/>
            </Name>
            <Condition>
                <xsl:value-of select="Condition/Value"/>
            </Condition>
            
            <xsl:apply-templates select="ancestor::Root/ReceiverInterfaces
                [Receiver/child::* = key('Receiver',Root/Receivers/ReceiverRule/Receiver)]"/>
        
        </Receiver>
        
    </xsl:template>
    
    <xsl:template match="ReceiverInterfaces">
        <xsl:apply-templates select="ReceiverInterfaceRule"/>
    </xsl:template>
    
    <xsl:template match="ReceiverInterfaceRule">
        <Rule>
            <xsl:value-of select="Rule"/>
        </Rule>
    </xsl:template>
    
</xsl:stylesheet>

produces this XML output:

<?xml version="1.0" encoding="UTF-8"?>
<ReceiverList>
    <Receiver>
        <Name>party1 SYS1</Name>
        <Condition>Condition 1</Condition>
    </Receiver>
    <Receiver>
        <Name>party2 SYS2</Name>
        <Condition>Condition 2</Condition>
    </Receiver>
</ReceiverList>

But I am expecting this output:

<?xml version="1.0" encoding="UTF-8"?>
<ReceiverList>
    <Receiver>
        <Name>party1 SYS1</Name>
        <Condition>Condition 1</Condition>
        <Rule>Rule 1 sytem 1</Rule>
        <Rule>Rule 2 system 1</Rule>
    </Receiver>
    <Receiver>
        <Name>party2 SYS2</Name>
        <Condition>Condition 2</Condition>
        <Rule>Rule 1 system 2</Rule>
        <Rule>Rule 2 system 2</Rule>
    </Receiver>
</ReceiverList>

somehow my key is not recognized. I appreciate any hint on what I am doing wrong. Thank you, Peter

question from:https://stackoverflow.com/questions/66052907/xslt-1-0-key-not-working-in-selecting-nodes

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I think instead of

<xsl:apply-templates select="ancestor::Root/ReceiverInterfaces
            [Receiver/child::* = key('Receiver',Root/Receivers/ReceiverRule/Receiver)]"/>

all you want is

<xsl:apply-templates select="key('Receiver', concat(Receiver/party, Receiver/system))/ReceiverInterfaceRule"/>

with the key as

<xsl:key name="Receiver" match="ReceiverInterfaces" use="concat(Receiver/party, Receiver/system)"/>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...