• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 44
  • Last Modified:

Using XSLT to convert XML configuration files

Hello

I have XML configuration files with the following (simplified) flat structure :
<MyEthernet Activity="true" DefaultGateway="192.168.0.253" PortNumber="1" EthId="IDa2"/>             
<MyEthernet Activity="true" DefaultGateway="193.168.0.253" PortNumber="2" EthId="IDa4"/>
<MyStreamer Activity="true" DestIpAddress="239.0.0.1" RtpId="IDa3" EthRef="IDa2"/>
...

Open in new window

I would like to convert like this:
<MyEthernet Activity="true" DefaultGateway="192.168.0.253" PortNumber="1" EthId="IDa2">             
   <MyStreamer Activity="true" DestIpAddress="239.0.0.1" RtpId="IDa3"/>
</MyEthernet>
<MyEthernet Activity="true" DefaultGateway="193.168.0.253" PortNumber="2" EthId="IDa4"/>

Open in new window


Can it be done using xslt and template matching? I used it before to match/correct single values, but never to move around tags.
0
FabClement
Asked:
FabClement
  • 3
1 Solution
 
Geert BormansInformation ArchitectCommented:
You can easily do this using XSLT.

Just use a key that indexes the MyStreamer elements by their @EthRef

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:key name="str" match="MyStreamer" use="@EthRef"/>
    
    <xsl:template match="MyEthernet">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="key('str', @EthId)" mode="inner"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="MyStreamer"/>

    <xsl:template match="MyStreamer" mode="inner">
        <xsl:copy>
            <xsl:copy-of select="@*[not(name() = 'EthRef')]"/>
        </xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>

Open in new window


You might need to add a template for the root element
(and you might hit an issue with a default namespace on the root element)
0
 
StarbucksDrinkerCommented:
XSLT will not process multiple root elements.  If you can wrap your config nodes inside one root (called anything, as long as it's different from your existing nodes), then wrap your <xsl:template match="MyEthernet"> inside <xsl:template match="/"> and you should be good to go!
0
 
Geert BormansInformation ArchitectCommented:
Hi Starbucksdrinker.
I think you simply did not have enough Starbucks today :-)
You can not wrap an xsl:template inside another xsl:template
that simply is illegal XSLT

You are right, in order to have wellformed XML there needs to be a container root element.
But you are wrong again in the "called anything but... " There is no reason at all why the root element needs to have a different name. As long as the match statement in the xsl:template is specific enough to differentiate between match="/MyEthernet" for the root

You can have a template match="/" or match="/MyEthernet"
and inside there call out for matching nodes against the other templates
by using xsl:apply-templates inside a template.
But my example shows everything the original poster needs to get started

Brings me to the point... when will this question be closed?
0
 
Geert BormansInformation ArchitectCommented:
This is an excellent example of adding hierarchy to a flat XML, based on ID and reference IDs (prim key foreign key relation so to speak)
The solution is relevant in a general sense
Please accept https:#a37765199
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now