xmlxslt

Translating XML using a stylesheet: multiple child elements


I have a large XML file of company data. I am trying to extract the name data so that it can be read into a flat table in a 3rd party application. Up until now I have successfully managed this with a stylesheet. However, I am struggling to retrieve the data from the second child element of <EntityName> that sits within the <NameValue> element at the same level as <Suffix>.

Here is the XML, redacted and simplified:

 <?xml version="1.0"?>
<PFA date="202406042200" type="full">
    <Records>
        <Entity id="3415002" action="add" date="18-Apr-2019">
            <NameDetails>
                <Name NameType="Primary Name">
                    <NameValue>
                        <EntityName>My Company</EntityName>
                    </NameValue>
                </Name>
                <Name NameType="Also Known As">
                    <NameValue>
                        <Suffix>Ltd</Suffix>
                        <EntityName>My Favourite Company</EntityName>
                    </NameValue>
                </Name>
                <Name NameType="Formerly Known As">
                    <NameValue>
                        <Suffix>Incorporated</Suffix>
                        <EntityName>Hullabaloo</EntityName>
                    </NameValue>
                </Name>
            </NameDetails>
        </Entity>
    </Records>
</PFA>

Here is the stylesheet:

<?xml version="1.0"?>
<xsl:stylesheet version = "1.0" xmlns="http://www.mycompany.com/2008/" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
    <xsl:output method="xml"/>

    <xsl:template match="/">
        <data>
            <record skip="true">
                <value name="Id" type="string"/>
                <value name="NameType" type="string"/>
                <value name="Suffix" type="string"/>
                <value name="EntityName" type="string"/>
            </record>
            <xsl:apply-templates select="/PFA/Records/Entity"/>
        </data>
    </xsl:template>

    <xsl:template match="Entity">
        <xsl:apply-templates select="NameDetails/Name/NameValue/Suffix"/>
    </xsl:template>
    
    <xsl:template match="Name/NameValue/Suffix">
            
        <record>
            <value name="Id"><xsl:value-of select="../../../../@id"/></value>
            <value name="NameType"><xsl:value-of select="../../@NameType"/></value>
            <value name="Suffix"><xsl:value-of select="."/></value>
            <value name="EntityName"><xsl:value-of select="."/></value>
        </record>       
        
    </xsl:template>
    
</xsl:stylesheet>

As can be seen below, this is successfully retrieving the Id, NameType and Suffix data. However, I cannot work out how to return the EntityName data for each record. Instead it repeats the Suffix data. Note that the Primary Name record is not retrieved at all since there is no Suffix data:

enter image description here

Finally, here is what I would like, with the EntityName included:

enter image description here

Many thanks for any assistance or advice.


Solution

  • I think you want to do something like:

    <xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" 
    xmlns="http://www.mycompany.com/2008/">
    <xsl:output method="xml" indent="yes"/>
    
    <xsl:template match="/PFA">
        <data>
            <record skip="true">
                <value name="Id" type="string"/>
                <value name="NameType" type="string"/>
                <value name="Suffix" type="string"/>
                <value name="EntityName" type="string"/>
            </record>
            <xsl:apply-templates select="Records/Entity"/>
        </data>
    </xsl:template>
    
    <xsl:template match="Entity">
        <xsl:apply-templates select="NameDetails/Name">
            <xsl:with-param name="id" select="@id"/>
        </xsl:apply-templates>
    </xsl:template>
    
    <xsl:template match="Name">
        <xsl:param name="id"/>
        <record>
            <value name="Id">
                <xsl:value-of select="$id"/>
            </value>
            <value name="NameType">
                <xsl:value-of select="@NameType"/>
            </value>
            <value name="Suffix">
                <xsl:value-of select="NameValue/Suffix"/>
            </value>
            <value name="EntityName">
                <xsl:value-of select="NameValue/EntityName"/>
            </value>
        </record>       
    </xsl:template>
    
    </xsl:stylesheet>