Correlating related items using XSLT

2019-09-12 07:14发布

问题:

I have the following xml input,

<Adult>
    <Parent>
        <Id>1</Id>
        <Name>Nick</Name>
        <Age>32</Age>
    </Parent>
    <Parent>
        <Id>2</Id>
        <Name>Michael</Name>
        <Age>35</Age>
    </Parent>
    <Information xmlns="http://ws.apache.org/ns/synapse" xmlns:ns="www.abc.com">
        <Children xmlns="">
            <Child>
                <Name>Anne</Name>
                <Gender>Female</Gender>
                <ParentId>1</ParentId>
            </Child>
            <Child>
                <Name>Will</Name>
                <Gender>Male</Gender>
                <ParentId>1</ParentId>
            </Child>
            <Child>
                <Name>Carney</Name>
                <Gender>Female</Gender>
                <ParentId>2</ParentId>
            </Child>
        </Children>
    </Information>
</Adult>

Currently I have all the children under a root element. But I need to group each child with it's associated parent. For an example all the children with parentId = 1 should come under the parent element with Id - 1. Finally it should appear as follows.

<Adult>
    <Parent>
        <Id>1</Id>
        <Name>Nick</Name>
        <Age>32</Age>
         <Children>
            <Child>
                <Name>Anne</Name>
                <Gender>Female</Gender>
                <ParentId>1</ParentId>
            </Child>
            <Child>
                <Name>Will</Name>
                <Gender>Male</Gender>
                <PareinId>1</PareinId>
            </Child>
        </Children>
    </Parent>
    <Parent>
        <Id>2</Id>
        <Name>Michael</Name>
        <Age>35</Age>
         <Children>
            <Child>
                <Name>Carney</Name>
                <Gender>Female</Gender>
                <ParentId>2</ParentId>
            </Child>
        </Children>
    </Parent>
</Adult>

Can someone suggest me a way to get this done. Any help would be appreciated.

回答1:

XSLT has a built-in key mechanism to resolve cross-references:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:syn="http://ws.apache.org/ns/synapse"
exclude-result-prefixes="syn">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="child" match="Child" use="ParentId" />

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

<xsl:template match="Parent">
    <xsl:copy>
        <xsl:apply-templates/>
        <Children>
            <xsl:apply-templates select="key('child', Id)"/>
        </Children>
    </xsl:copy>
</xsl:template>

<xsl:template match="syn:Information"/>

</xsl:stylesheet>