Split KML into subfiles with XSLT, nearly there but can't get it to work

不想你离开。 提交于 2019-12-14 02:19:13

问题


I have a KML file with country borders

    <Document>
    ...
        <Folder>
            <name>Countries</name>
            <Style>
                <ListStyle>
                    <listItemType>checkHideChildren</listItemType>
                    <bgColor>00ffffff</bgColor>
                    <maxSnippetLines>2</maxSnippetLines>
                </ListStyle>
            </Style>
            <Folder>
                <name>Labels</name>
                <Placemark>
                    <name>Angola</name>
                    <styleUrl>#NoneIconStyle</styleUrl>
                    <Point>
                        <coordinates>17.5379654426636,-12.2994772211426,0</coordinates>
                    </Point>
                </Placemark>
            ... ignore these

            <Folder>
                <name>A -</name>
                <Placemark>
                    <name>Afghanistan</name>
                    <Polygon>
                        <outerBoundaryIs>
                            <LinearRing>
                                <coordinates>
65.62729644775391,37.33319854736328,0 65.64692687988283,37.45888137817383,0 65.70137023925781,37.53693008422852,0 65.76608276367188,37.53416061401367,0 65.7855224609375,37.56887817382813,0 66.30274963378906,37.32360076904297,0 66.53876495361328,37.36051177978516,0 66.58690643310547,37.36803817749023,0 66.66525268554688,37.33832168579102,0 66.74442291259766,37.36137008666992,0 67.02163696289063,37.37720108032227,0 67.20025634765625,37.24665069580078,0 67.22942352294922,37.19192886352539,0 67.26637268066406,37.18526077270508,0 67.42440795898438,37.23498916625977,0 67.52163696289063,37.27248001098633,0 67.55745697021484,37.21554183959961,0 67.64940643310547,37.24608993530273,0 67.77413940429689,37.20608901977539,0 67.77715301513672,37.18579864501953,0 

It has every country. I want to make a separate files for each country. I want to ignore the initial 'lables' folder and move the Folder with the coordinates one up in the tree. So Afghanistan.KML would be

<?xml version="1.0" encoding="UTF-8"?>
<kml>
    <Document>
        <Folder>
            <name>Countries</name>
                <Placemark>
                    <name>Afghanistan</name>
                    <Polygon>
                        <outerBoundaryIs>
                            <LinearRing>
                                <coordinates>
65.62729644775391,37.33319854736328,0 65.64692687988283,37.45888137817383,0 65.70137023925781,37.53693008422852,0 65.76608276367188,37.53416061401367,0 65.7855224609375,37.56887817382813,0 66.30274963378906,37.32360076904297,0 66.53876495361328,37.36051177978516,0 66.58690643310547,37.36803817749023,0 66.66525268554688,37.33832168579102,0 66.74442291259766,37.36137008666992,0 67.02163696289063,37.37720108032227,0 67.20025634765625,37.24665069580078,0 67.22942352294922,37.19192886352539,0 67.26637268066406,37.18526077270508,0 67.42440795898438,37.23498916625977,0 67.52163696289063,37.27248001098633,0 67.55745697021484,37.21554183959961,0 67.64940643310547,37.24608993530273,0 67.77413940429689,37.20608901977539,0 67.77715301513672,37.18579864501953,0 
    ...etc

My XSLT nearly works

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" version="1.0" omit-xml-declaration="yes"/>
    <xsl:template match="/">
        <xsl:apply-templates select="*[local-name()='kml']/*[local-name()='Document']"/>
    </xsl:template>
    <xsl:template match="*[local-name()='kml']/*[local-name()='Document']">
        <Document>
            <xsl:apply-templates select="*[local-name()='Folder']"/>
        </Document>
    </xsl:template>
    <xsl:template match="*[local-name()='Folder']">
        <xsl:apply-templates select="*[local-name()='Folder' or local-name()='Placemark']"/>
    </xsl:template>
    <xsl:template match="*[local-name()='Placemark']">
        <name>{name}</name> <!-- !! -->
        <xsl:result-document method="xml" href="d:\downloads\countries\{name}.xml">-->
        <xsl:apply-templates select="*[local-name()='Polygon']"/>
        </xsl:result-document>
    </xsl:template>
    <xsl:template match="*[local-name()='Polygon']">
        <Polygon>
            <xsl:apply-templates select="*[local-name()='outerBoundaryIs']"/>
        </Polygon>
    </xsl:template>
    <xsl:template match="*[local-name()='outerBoundaryIs']">
        <outerBoundaryIs>
            <xsl:apply-templates select="*[local-name()='LinearRing']"/>
        </outerBoundaryIs>
    </xsl:template>
    <xsl:template match="*[local-name()='LinearRing']">
        <LinearRing>
                </LinearRing>
        <xsl:apply-templates select="*[local-name()='coordinates']"/>
    </xsl:template>
    <xsl:template match="*[local-name()='coordinates']">
        <coordinates>
            <xsl:value-of select="."/>
        </coordinates>
    </xsl:template>
</xsl:stylesheet>

but I can't get the processor to recognise the 'name' and switch files (marked by <!-- !! -->).

Is there an XSL wizard whou could help me out?

Thanks!


回答1:


The following stylesheet works with the http://www.calvert.ch/download/world-borders.kml data (note xpath-default-namespace).

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xpath-default-namespace="http://www.opengis.net/kml/2.2"
        version="2.0">

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

  <xsl:template match="/">
    <xsl:apply-templates select="//Folder[matches(name,'[A-Z] -')]"/>
  </xsl:template>

  <xsl:template match="Folder">
    <xsl:for-each select="Placemark">
      <xsl:result-document href="{name}.xml">
      <kml>
        <Document>
          <Folder>
            <name>Countries</name>
            <xsl:copy-of select="."/>
          </Folder>  
        </Document>
      </kml>
    </xsl:result-document>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>



回答2:


This gives you the desired output on your sample input;

<?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"
  exclude-result-prefixes="xs"
  version="2.0">

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

  <xsl:template match="/kml">
    <xsl:apply-templates select="Document/Folder[name/text()='Countries']/Folder[name/text()='Labels']/Folder[matches(name/text(),'[A-Z] -')]"/>
  </xsl:template>

  <xsl:template match="Folder">
    <xsl:variable name="country" select="Placemark/name/text()"/>
    <xsl:result-document href="{$country}.xml">
      <kml>
        <Document>
          <Folder>
            <name>Countries</name>
            <xsl:copy-of select="Placemark"/>
          </Folder>  
        </Document>
      </kml>
    </xsl:result-document>
  </xsl:template>

</xsl:stylesheet>

It makes a couple of assumptions...

  1. The document structure is as you have shown it, where the countries are actually within the Labels folder.
  2. Country folders will be contained within alphabet-letter folders that match the given regular expression



回答3:


I can't get the processor to recognise the 'name' and switch files (marked by <!-- !! -->).

  <name>{name}</name> <!-- !! -->
  <xsl:result-document method="xml" href="d:\downloads\countries\{name}.xml">

I think you should better write somthing like this:

        <name><xsl:value-of select="name"/></name>
        <xsl:variable name="filename"
          select="concat('d:\downloads\countries\',name,'.xml')" />
        <xsl:result-document method="xml" href="{$filename}">

This is finally what would be more readable (on the same line of the other answers (+1)):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xpath-default-namespace="http://www.opengis.net/kml/2.2"
    version="2.0">
    <xsl:output indent="yes"/>

    <xsl:template match="/*/*/*/*[matches(name,'[A-Z]\s+-')]/Placemark">
        <xsl:result-document href="d:\downloads\countries\{name}.xml">
            <kml>
                <Document>
                    <Folder>
                        <name>Countries</name>
                        <xsl:copy-of select="."/>
                    </Folder>  
                </Document>
            </kml>
        </xsl:result-document>
    </xsl:template>

</xsl:stylesheet>


来源:https://stackoverflow.com/questions/6846064/split-kml-into-subfiles-with-xslt-nearly-there-but-cant-get-it-to-work

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!