XSL to create attribute based folders

I am using XSL to convert XML to KML for viewing in Google Earth. I could create folders for each "IT_Type" in the XML example below

Currently, XML is being converted to a folder structure as follows:

  • Point
    • Vss1
    • Vss2
    • Cab1
    • CaB2
    • Dms1
    • Dms2
  • Line
    • From: to:
    • From: To:
    • From: to:

It should be structured into folders such as this, with a folder for each IT_Type in the parent folders of Point and Line.

  • Point
    • Vss
      • Vss1
      • Vss2
    • Cabinet
      • Cab1
      • CaB2
    • Dms
      • Dms1
      • Dms2
  • Line
    • viewing
      • From: to:
    • Cabinet
      • From: to:
    • Other
      • From: to:

What is the best way to configure XSL for this? Would performance be a problem for large datasets?

Any advice or sample code is welcome.

Thanks.

See below XML example

<Parents> <Point> <Row IT_ID="116" IT_Name="VSS1" IT_Type="VSS" GPSLat="43.953000000000" GPSLong="-85.671800000000" /> <Row IT_ID="117" IT_Name="VSS2" IT_Type="VSS" GPSLat="43.966900000000" GPSLong="-85.678900000000" /> <Row IT_ID="122" IT_Name="Cab1" IT_Type="Cabinet" GPSLat="43.903100000000" GPSLong="-85.677100000000" /> <Row IT_ID="123" IT_Name="Cab2" IT_Type="Cabinet" GPSLat="43.913500000000" GPSLong="-85.677300000000" /> <Row IT_ID="254" IT_Name="DMS1" IT_Type="DMS" GPSLat="43.903100000000" GPSLong="-85.677100000000" /> <Row IT_ID="255" IT_Name="DMS2" IT_Type="DMS" GPSLat="43.989400000000" GPSLong="-85.676800000000" /> </Point> <Line> <Row LINE_ID="1117" IT_Type="Handhole" FROM_SYSTEM_ID="2127" TO_SYSTEM_ID="1947" FromLat="43.438474034300" FromLong="-83.195331982500" ToLat="43.437072542900" ToLong="-83.193657308800"> <Row2 LINE_ID="1117" CONDUIT_NUMBER="1" CONDUIT_TYPE="Fiber" FIBER_NUMBER="1" FIBER_TYPE="Trunk" STRANDS="96" /> <Row2 LINE_ID="1117" CONDUIT_NUMBER="2" CONDUIT_TYPE="Empty" FIBER_NUMBER="" FIBER_TYPE="" STRANDS="" /> <Row2 LINE_ID="1117" CONDUIT_NUMBER="3" CONDUIT_TYPE="Empty" FIBER_NUMBER="" FIBER_TYPE="" STRANDS="" /> <Row2 LINE_ID="1117" CONDUIT_NUMBER="4" CONDUIT_TYPE="Empty" FIBER_NUMBER="" FIBER_TYPE="" STRANDS="" /> </Row> <Row LINE_ID="997" IT_Type="Cabinet" FROM_SYSTEM_ID="2011" TO_SYSTEM_ID="2012" FromLat="43.482705558800" FromLong="-83.260130135400" ToLat="43.482694479700" ToLong="-83.260107590500"> <Row2 LINE_ID="997" CONDUIT_NUMBER="1" CONDUIT_TYPE="Other" FIBER_NUMBER="" FIBER_TYPE="" STRANDS="" /> </Row> <Row LINE_ID="1220" IT_Type="Other" FROM_SYSTEM_ID="2415" TO_SYSTEM_ID="2413" FromLat="43.624664303600" FromLong="-83.086848805700" ToLat="43.624645615600" ToLong="-83.086770805500"> <Row2 LINE_ID="1220" CONDUIT_NUMBER="1" CONDUIT_TYPE="Fiber" FIBER_NUMBER="1" FIBER_TYPE="Dist" STRANDS="12" /> <Row2 LINE_ID="1220" CONDUIT_NUMBER="2" CONDUIT_TYPE="Electric" FIBER_NUMBER="" FIBER_TYPE="" STRANDS="" /> </Row> </Line> </Parents> 

Please see below for my XSL:

 <xsl:template match="Parents"> <Folder> <name> Point </name> <xsl:for-each select="Point/Row"> <Placemark> <name> <xsl:value-of select="@IT_Name"/> </name> <description> <xsl:value-of select="@Location"/> </description> <styleUrl> <xsl:value-of select="concat($hash,@IT_Type)"/> </styleUrl> <Point> <coordinates> <xsl:value-of select="@GPSLong"/>, <xsl:value-of select="@GPSLat"/> </coordinates> </Point> </Placemark> </xsl:for-each> </Folder> <Folder> <name> Line </name> <xsl:for-each select="Line/Row"> <Placemark> <name> From: <xsl:value-of select="@FROM_SYSTEM_ID"/> to: <xsl:value-of select="@TO_SYSTEM_ID"/> </name> <description> <xsl:value-of select="@CONDUIT_NUMBER"/> </description> <styleUrl> <xsl:value-of select="concat($hash,@IT_Type)"/> </styleUrl> <LineString> <tessellate>1</tessellate> <coordinates> <xsl:value-of select="@FromLong"/>,<xsl:value-of select="@FromLat"/>,0 <xsl:value-of select="@ToLong"/>,<xsl:value-of select="@ToLat"/>,0 </coordinates> </LineString> </Placemark> </xsl:for-each> </Folder> </xsl:template> 
+2
source share
1 answer

Sorry to have completely revised your original template, but the general way to do this (in XSLT 1.0) is to use the Meunchian method for multi-level grouping. In your specific case, you can create xsl:key based on the concatenation of @IT_Type and the parent Row element.


For example, this XSLT 1.0 (tested in Saxon 6.5 )

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> <xsl:strip-space elements="*"/> <xsl:key name="kIT_Type" match="Row" use="concat( name(parent::node()),@IT_Type )"/> <xsl:template match="Parents/*"> <Folder> <name><xsl:value-of select="name()"/></name> <xsl:apply-templates select="Row[ generate-id(.) = generate-id(key('kIT_Type', concat(name(parent::node()),@IT_Type))[1]) ]"/> </Folder> </xsl:template> <xsl:template match="Row"> <Folder> <name><xsl:value-of select="@IT_Type"/></name> <xsl:apply-templates select="key('kIT_Type', concat(name(parent::node()),@IT_Type))" mode="placemark"/> </Folder> </xsl:template> <xsl:template match="Row[parent::Point]" mode="placemark"> <Placemark> <name> <xsl:value-of select="@IT_Name"/> </name> <description> <!--xsl:value-of select="@Location"/--> </description> <styleUrl> <!--xsl:value-of select="concat($hash,@IT_Type)"/--> </styleUrl> <Point> <coordinates> <xsl:value-of select="@GPSLong"/>, <xsl:value-of select="@GPSLat"/> </coordinates> </Point> </Placemark> </xsl:template> <xsl:template match="Row[parent::Line]" mode="placemark"> <Placemark> <name> From: <xsl:value-of select="@FROM_SYSTEM_ID"/> to: <xsl:value-of select="@TO_SYSTEM_ID"/> </name> <description> <xsl:value-of select="@CONDUIT_NUMBER"/> </description> <styleUrl> <!-- xsl:value-of select="concat($hash,@IT_Type)"/--> </styleUrl> <LineString> <tessellate>1</tessellate> <coordinates> <xsl:value-of select="@FromLong"/>,<xsl:value-of select="@FromLat"/>,0 <xsl:value-of select="@ToLong"/>,<xsl:value-of select="@ToLat"/>,0 </coordinates> </LineString> </Placemark> </xsl:template> <xsl:template match="Row2"/> </xsl:stylesheet> 

Applied at your input, creates RTF:

 <Folder> <name>Point</name> <Folder> <name>VSS</name> <Placemark> <name>VSS1</name> <description/> <styleUrl/> <Point> <coordinates>-85.671800000000, 43.953000000000</coordinates> </Point> </Placemark> <Placemark> <name>VSS2</name> <description/> <styleUrl/> <Point> <coordinates>-85.678900000000, 43.966900000000</coordinates> </Point> </Placemark> </Folder> <Folder> <name>Cabinet</name> <Placemark> <name>Cab1</name> <description/> <styleUrl/> <Point> <coordinates>-85.677100000000, 43.903100000000</coordinates> </Point> </Placemark> <Placemark> <name>Cab2</name> <description/> <styleUrl/> <Point> <coordinates>-85.677300000000, 43.913500000000</coordinates> </Point> </Placemark> </Folder> <Folder> <name>DMS</name> <Placemark> <name>DMS1</name> <description/> <styleUrl/> <Point> <coordinates>-85.677100000000, 43.903100000000</coordinates> </Point> </Placemark> <Placemark> <name>DMS2</name> <description/> <styleUrl/> <Point> <coordinates>-85.676800000000, 43.989400000000</coordinates> </Point> </Placemark> </Folder> </Folder> <Folder> <name>Line</name> <Folder> <name>Handhole</name> <Placemark> <name> From: 2127 to: 1947</name> <description/> <styleUrl/> <LineString> <tessellate>1</tessellate> <coordinates>-83.195331982500,43.438474034300,0 -83.193657308800,43.437072542900,0 </coordinates> </LineString> </Placemark> </Folder> <Folder> <name>Cabinet</name> <Placemark> <name> From: 2011 to: 2012</name> <description/> <styleUrl/> <LineString> <tessellate>1</tessellate> <coordinates>-83.260130135400,43.482705558800,0 -83.260107590500,43.482694479700,0 </coordinates> </LineString> </Placemark> </Folder> <Folder> <name>Other</name> <Placemark> <name> From: 2415 to: 2413</name> <description/> <styleUrl/> <LineString> <tessellate>1</tessellate> <coordinates>-83.086848805700,43.624664303600,0 -83.086770805500,43.624645615600,0 </coordinates> </LineString> </Placemark> </Folder> </Folder> 
+1
source

All Articles