0

I want to do one transformation using XSLT. As per below sample, there are multiple EmpRecord available and each EmpRecord contains EmpDept and Profile of available employees under that Department.

XML:

<Employee>
    <EmpRecord>
        <EmpDept>Accounting</EmpDept>
        <EmpData>
            <Name>Joy</Name>
            <Age>32</Age>
        </EmpData>
    </EmpRecord>
    <EmpRecord>
        <EmpDept>Finance</EmpDept>
    </EmpRecord>
    <EmpRecord>
        <EmpDept>IT</EmpDept>
        <EmpData>
            <Name>Sam</Name>
            <Age>27</Age>
        </EmpData>
        <EmpData>
            <Name>John</Name>
            <Age>25</Age>
        </EmpData>
        <EmpData>
            <Name>Ricky</Name>
            <Age>31</Age>
        </EmpData>
    </EmpRecord>
</Employee>

Expected Output :

<Employee>
    <EmpRecord>
        <Department>Accounting</Department>
        <EmpData>
            <EmpName>Joy</EmpName>
            <Age>32</Age>
        </EmpData>
    </EmpRecord>
    <EmpRecord>
        <Department>IT</Department>
        <EmpData>
            <EmpName>Sam</EmpName>
            <Age>27</Age>
        </EmpData>
        <EmpData>
            <EmpName>John</EmpName>
            <Age>25</Age>
        </EmpData>
        <EmpData>
            <EmpName>Ricky</EmpName>
            <Age>31</Age>
        </EmpData>
    </EmpRecord>
</Employee>

I am able to get all available EmpData but unable to fetch EmpDept.

XSLT used:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<Employee>
<xsl:for-each select="/Employee/EmpRecord/EmpData">
<Department><xsl:value-of select="./EmpDept"/></Department>
<EmpData>
<EmpName><xsl:value-of select="./Name"/></EmpName>
<Age><xsl:value-of select="./Age"/></Age>
</EmpData>
</xsl:for-each>
</Employee>

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

So I want only those EmpDept which has at least one employee available.

2 Answers 2

2

Try it this way:

XSLT 1.0

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

<xsl:template match="/Employee">
    <Employee>
        <xsl:for-each select="EmpRecord[EmpData]">
            <EmpRecord>
                <Department>
                    <xsl:value-of select="EmpDept"/>
                </Department>
                <xsl:for-each select="EmpData">
                    <EmpData>
                        <EmpName>
                            <xsl:value-of select="Name"/>
                        </EmpName>
                        <xsl:copy-of select="Age"/>
                    </EmpData>
                </xsl:for-each>
            </EmpRecord>
        </xsl:for-each>
    </Employee>
</xsl:template>

</xsl:stylesheet>

Or, if you prefer:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="EmpRecord[not(EmpData)]"/>

<xsl:template match="EmpDept">
    <Department>
        <xsl:apply-templates/>
    </Department>
</xsl:template>

<xsl:template match="Name">
    <EmpName>
        <xsl:apply-templates/>
    </EmpName>
</xsl:template>

</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

Comments

0

What you actually want to do is: copy everything from source to target xml, aside from EmpRecord not containing any EmpData. Right? Try this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output encoding="UTF-8" method="xml" version="1.0" indent="yes"/>
    <!-- identity template -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <!-- specific part -->
    <xsl:template match="EmpRecord[not(EmpData)]"/>
</xsl:stylesheet>

"identity template" copies everything, "specific part" deletes the unwanted elements.

1 Comment

Sorry if my expected output is misleading, actually I don't want to copy exactly. There is tag and structure change required in my actual work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.