Home > database >  XML element transforming using XSLT
XML element transforming using XSLT

Time:11-16

I'm working on a 3D visualization of a network graph and the input to the 3D Visualization is an XML file with nodes and edges. The XML file is the output of a network analysis tool without proper 3d visualization capability. Unfortunately, this XML file cannot be read properly in the tool where I'm doing the 3D visualization. I'm not an expert in XML but know what the file should be transformed into, to make it a readable XML for my 3D visualization tool. I've been trying for 2-3 days now to transform the XML with XSLT but unable to solve. Hopefully someone can help.. The XML looks as following:

<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
    <key id="desc" for="node" attr.name="Description" attr.type="string"/>
    <key id="x" for="node" attr.name="x" attr.type="float"/>
    <key id="y" for="node" attr.name="y" attr.type="float"/>
    <key id="z" for="node" attr.name="z" attr.type="float"/>
    <key id="d1" for="node" attr.name="Node Component Identifier" attr.type="string"/>
    <key id="d2" for="node" attr.name="Node Degree" attr.type="int"/>
 <graph edgedefault="directed">
       <node id="n0">
            <data key="d1">Component 1</data>
            <data key="d2">10</data>
            <data key="desc">Person Alpha</data>
            <data key="x">17.0119</data>
            <data key="y">-1.36144</data>
            <data key="z">2.80569</data>
        </node>
       <node id="n1">
            <data key="d1">Component 1</data>
            <data key="d2">10</data>
            <data key="desc">Person Beta</data>
            <data key="x">11.091</data>
            <data key="y">1.183</data>
            <data key="z">-3.55</data>
        </node>
</graph>
</graphml>

As an output, I need a much simpler format that looks like this (remove keys, remove d2):

<graphml>
<graph egedefault="directed">
       <node id="n0">
            <component>Component 1</component>
            <desc>Person Alpha</desc>
            <x>17.0119</x>
            <y>-1.36144</y>
            <z>2.80569</z>
        </node>
       <node id="n1">
            <component>Component 1</component>
            <desc>Person Beta</desc>
            <x>11.091</x>
            <y>1.183</y>
            <z>-3.55</z>
        </node>
</graph>
</graphml>

Is there someone that can help me to achieve my goal using XSLT transformation?

I tried severel tips including:

They are all a bit different from my example and therefore not getting the right end result.

CodePudding user response:

Here's an XSLT 1.0 solution. (Some elements need to be renamed and your output is not in any namespace.)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:graph="http://graphml.graphdrawing.org/xmlns"
    exclude-result-prefixes="graph"
    version="1.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="graph:graphml">
    <graphml>
      <xsl:apply-templates select="*"/>
    </graphml>
  </xsl:template>
  
  <xsl:template match="graph:key"/>
  
  <xsl:template match="graph:graph">
    <graph>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="*"/>
    </graph>
  </xsl:template>
  
  <xsl:template match="graph:node">
    <node>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="*"/>
    </node>
  </xsl:template>
  
  <xsl:template match="graph:data[@key='d1']">
    <component>
      <xsl:value-of select="."/>
    </component>
  </xsl:template>
  
  <xsl:template match="graph:data[@key='d2']"/>
  
  <xsl:template match="graph:data[@key='desc']">
    <desc>
      <xsl:value-of select="."/>
    </desc>
  </xsl:template>
  
  <xsl:template match="graph:data[@key='x']">
    <x>
      <xsl:value-of select="."/>
    </x>
  </xsl:template>
  
  <xsl:template match="graph:data[@key='y']">
    <y>
      <xsl:value-of select="."/>
    </y>
  </xsl:template>
  
  <xsl:template match="graph:data[@key='z']">
    <z>
      <xsl:value-of select="."/>
    </z>
  </xsl:template>
  
</xsl:stylesheet>

See it working here : https://xsltfiddle.liberty-development.net/nbL5Ydc

CodePudding user response:

Here is an XSLT 2.0 Solution

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:b="http://graphml.graphdrawing.org/xmlns"
    exclude-result-prefixes="xs b"
    version="2.0">
    <xsl:output method="xml" indent="yes"></xsl:output>
    <xsl:template  match="/b:graphml/b:graph">
        <graphml>
            <graph egedefault="{@edgedefault}">
                <xsl:for-each select="b:node">
                    <node id="{@id}">
                        <component><xsl:value-of select="b:data[@key='d1']"/></component>
                        <desc><xsl:value-of select="b:data[@key='desc']"/></desc>
                        <x><xsl:value-of select="b:data[@key='x']"/></x>
                        <y><xsl:value-of select="b:data[@key='y']"/></y>
                        <z><xsl:value-of select="b:data[@key='z']"/></z>
                    </node>
                </xsl:for-each>
            </graph>
        </graphml>
    </xsl:template>
</xsl:stylesheet>
  • Related