Search code examples
xmlgoogle-mapsxsltkmlgoogle-earth

How to for each on each element of xsl that do not have the same name?


I have an XML document and I am trying to use XSLT to convert it into a KML document (to use on Google Earth). Here is a small part of my XML document :

 <rtc>
    <liste-trajets>
    </liste-trajets>
   <trajets>
    <metrobus>
        <bus-trajet no="800">
            <coordonnee lat="46.75183033" long="-71.33077615" />
            <coordonnee lat="46.75166296" long="-71.33102882" />
            <coordonnee lat="46.75156178" long="-71.33121051" />
            <coordonnee lat="46.75150417" long="-71.3313392" />
            <coordonnee lat="46.75143369" long="-71.33150566" />
            <coordonnee lat="46.75138512" long="-71.33162664" />
            <coordonnee lat="46.7513409" long="-71.33176994" />
            <coordonnee lat="46.75130584" long="-71.33188982" />
            <coordonnee lat="46.75128698" long="-71.33200995" />
            <coordonnee lat="46.75127417" long="-71.33216289" />
            <coordonnee lat="46.75127735" long="-71.33234357" />
            <coordonnee lat="46.75129765" long="-71.33252189" />
            <coordonnee lat="46.75133359" long="-71.33265202" />
            <coordonnee lat="46.75139087" long="-71.33281652" />
            <coordonnee lat="46.75145545" long="-71.33296673" />
            <coordonnee lat="46.75155389" long="-71.33316196" />                            
        </bus-trajet>
        <bus-trajet no="801">
            <coordonnee lat="46.75183033" long="-71.33077615" />
            <coordonnee lat="46.75166296" long="-71.33102882" />
            <coordonnee lat="46.75156178" long="-71.33121051" />
            <coordonnee lat="46.75150417" long="-71.3313392" />
            <coordonnee lat="46.75143369" long="-71.33150566" />
            <coordonnee lat="46.75138512" long="-71.33162664" />
            <coordonnee lat="46.7513409" long="-71.33176994" />
            <coordonnee lat="46.75130584" long="-71.33188982" />
            <coordonnee lat="46.75128698" long="-71.33200995" />
            <coordonnee lat="46.75127417" long="-71.33216289" />
            <coordonnee lat="46.75127735" long="-71.33234357" />
            <coordonnee lat="46.75129765" long="-71.33252189" />
            <coordonnee lat="46.75133359" long="-71.33265202" />
            <coordonnee lat="46.75139087" long="-71.33281652" />
            <coordonnee lat="46.75145545" long="-71.33296673" />
            <coordonnee lat="46.75155389" long="-71.33316196" />                            
        </bus-trajet>

    </metrobus>

    <lebus>
        <bus-trajet no="15">
            <coordonnee lat="46.75183033" long="-71.33077615" />
            <coordonnee lat="46.75166296" long="-71.33102882" />
            <coordonnee lat="46.75156178" long="-71.33121051" />
            <coordonnee lat="46.75150417" long="-71.3313392" />
            <coordonnee lat="46.75143369" long="-71.33150566" />
            <coordonnee lat="46.75138512" long="-71.33162664" />
            <coordonnee lat="46.7513409" long="-71.33176994" />
            <coordonnee lat="46.75130584" long="-71.33188982" />
            <coordonnee lat="46.75128698" long="-71.33200995" />
            <coordonnee lat="46.75127417" long="-71.33216289" />
            <coordonnee lat="46.75127735" long="-71.33234357" />
            <coordonnee lat="46.75129765" long="-71.33252189" />
            <coordonnee lat="46.75133359" long="-71.33265202" />
            <coordonnee lat="46.75139087" long="-71.33281652" />
            <coordonnee lat="46.75145545" long="-71.33296673" />
            <coordonnee lat="46.75155389" long="-71.33316196" />    
        </bus-trajet>
    </lebus>
 </trajets>
</rtc>

What I am unable to achieve/comprehend is selecting each nodes in rtc/trajets (metrobus,lebus,expressbus,couchetard). The problem is cannot do for each (rtc/trajets/elementX) because elementX has a different name everytime. The file is very large so i didn't copy it entirely basically the structure is as follows (should have made a XML schema...) rtc>trajets>metrobus,lebus,expressbus,couchetard>bus-trajets(all the bus lines for this categorie of bus)>coordinates of this bus line.

Here is what I've done so far in XSL

<?xml version="1.0" encoding="utf-8" ?>

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

        <xsl:template match="/">
<kml xmlns="http://www.opengis.net/kml/2.2"
     xmlns:gx="http://www.google.com/kml/ext/2.2">
            <Document>

                <Placemark>     
                    <LineString>
                         <xsl:for-each select="bus-trajet">
                        <Coordinates>
                            <xsl:for-each select="coordonnee">
                                <xsl:value-of select="long"/> , <xsl:value-of select="lat"/>
                            </xsl:for-each>             
                        </Coordinates>
                         </xsl:for-each>
                    </LineString>
                    <Style> 
                        <LineStyle>  
                            <color></color>
                        </LineStyle> 
                        <LabelStyle>
                            <color></color>
                        </LabelStyle>   
                    </Style>            
                </Placemark>

            </Document>
</kml>      


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

I'm also confused as to how to created a structure that can accommodate the category of the bus because after the tag it's directly a placemark(line of the bus with its coordinates).

Any help appreciated and sorry if half the code is in french...


Solution

  • At the moment you have this xsl:for-each

    <xsl:for-each select="/bus-trajet">
    

    But this is currently not achieving much because at the point you are positioned on the document node (due to the template match of /) so it is looking for a root element called bus-trajet.

    Now, what you could do is this...

     <xsl:for-each select="/rtc/trajets/*/bus-trajet">
    

    Note the use of * which will match any element. If you wanted to match only a subset of elements, you could do this...

    <xsl:for-each select="/rtc/trajets/*[self::metrobus or self::lebus]/bus-trajet">
    

    Alternatively, you could do this, which would match bus-traject at any level

     <xsl:for-each select="//bus-trajet">
    

    As a side note, you are doing this to get the co-ordinates...

    <xsl:value-of select="long"/> , <xsl:value-of select="lat"/>
    

    But it should be the following, as long and lat are attributes

    <xsl:value-of select="@long"/> , <xsl:value-of select="@lat"/>