问题
I have an XSLT which has the job of reformatting KML to GML.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.opengis.net/gml" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" exclude-result-prefixes="kml">
<xsl:output method="xml" indent="yes" encoding="utf-8" omit-xml-declaration="yes" />
<!-- Removes all nodes with any empty text -->
<xsl:template match="*[.='']"/>
<!-- Removes all nodes with any empty attribute -->
<xsl:template match="*[@*='']"/>
<xsl:template match="text()"/>
<xsl:template match="/">
<MultiSurface>
<surfaceMembers>
<xsl:apply-templates />
</surfaceMembers>
</MultiSurface>
</xsl:template>
<xsl:template match="kml:Placemark">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="kml:Point">
<!--<Point>
<xsl:apply-templates />
</Point>-->
</xsl:template>
<xsl:template match="kml:LineString">
<!--<LineString>
<xsl:apply-templates />
</LineString>-->
</xsl:template>
<xsl:template match="kml:Polygon">
<Polygon>
<xsl:apply-templates />
</Polygon>
</xsl:template>
<xsl:template match="kml:outerBoundaryIs">
<exterior>
<xsl:apply-templates />
</exterior>
</xsl:template>
<xsl:template match="kml:innerBoundaryIs">
<interior>
<xsl:apply-templates />
</interior>
</xsl:template>
<xsl:template match="kml:LinearRing">
<LinearRing>
<xsl:apply-templates />
</LinearRing>
</xsl:template>
<xsl:template match="kml:coordinates">
<posList>
<!--<xsl:value-of select="translate(., ',', ' ')" />-->
<xsl:call-template name="output-tokens">
<xsl:with-param name="list" select="." />
</xsl:call-template>
</posList>
</xsl:template>
<xsl:template name="output-tokens">
<xsl:param name="list" />
<xsl:variable name="newlist" select="concat(normalize-space($list), ' ')" />
<xsl:variable name="first" select="substring-before($newlist, ' ')" />
<xsl:variable name="remaining" select="substring-after($newlist, ' ')" />
<!-- long, lat, alt-->
<xsl:variable name="long" select="substring-before($first, ',')" />
<xsl:choose>
<xsl:when test="contains(substring-after($first, ','), ',')">
<xsl:variable name="lat" select="substring-before(substring-after($first, ','), ',')" />
<xsl:value-of select="concat($lat, ' ', $long, ' ')" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="lat" select="substring-after($first, ',')" />
<xsl:value-of select="concat($lat, ' ', $long, ' ')" />
</xsl:otherwise>
</xsl:choose>
<xsl:if test="$remaining">
<xsl:call-template name="output-tokens">
<xsl:with-param name="list" select="$remaining" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Normally our clients have given us KML files that have a kml opening tag as such:
<kml xmlns="http://www.opengis.net/kml/2.2">
And for this instance the XSLT works great to transform that KML file. However we got one today that had...
<kml xmlns="http://earth.google.com/kml/2.2">...</kml>
This does not work and I assume it is because the KMLs xmlns attribute is not set to: http://www.opengis.net/kml/2.2 or alternatively the XSLTs xmlns:kml is not set to: http://earth.google.com/kml/2.2
I tried the following but it did not work
xmlns:kml="http://www.opengis.net/kml/2.2 http://earth.google.com/kml/2.2"
I feel the answer will be stupidly simple but I have not stumbled across it yet and I am running out of stuff to try and Google. What do you guys suggest?
回答1:
It is important to understand that XML namespace prefixes are not inherently meaningful. They are merely a form of shorthand for namespace names, which are URIs that identify namespaces. It is the namespace name, as bound to a prefix via a namespace declaration attribute, that actually identifies the namespace and scopes names in a namespace-aware XML processor, such as an XSLT processor. As such, it does not make sense to try to bind one prefix to two alternative namespace names.
None of this has anything to do with the location of XML schema documents. Supposing, however, that the KML 2.2 you're talking about is the one described by the schema document at http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd, its namespace name is http://www.opengis.net/kml/2.2
, as is expressly specified by its schema. Instance documents are not at liberty to use a different namespace name (though they are at liberty to bind whatever namespace prefix they want to that name -- it doesn't have to be "kml").
Bottom line: there are only two possibilities:
The document provided by your client is malformed as a result of using the wrong namespace name. In this case, the best thing to do is to fix the namespace name in the client's file, or ask the client to do so. You could do that by editing it, or you could write a stylesheet to perform such a transformation. Either way, it might be a good idea to validate the resulting document against the schema to which you expect it to conform.
The document provided by your client is of a different XML document type (loose sense) than you expect and are prepared to handle. In this case, the only thing to do is to request a new file of the correct type from the client.
回答2:
Google's namespace is an extension of the KML standard: see https://developers.google.com/kml/documentation/kmlreference
So if you simply change your stylesheet to handle the different namespace, it may or may not work, depending on (a) whether the Google extensions are actually used, and (b) how robustly the stylesheet has been written to handle extensions (the template rules that discard any element having empty text or an empty attribute don't look like a particularly good start.)
Generally my advice when you have two variants of an XML vocabulary using different namespaces is to start by preprocessing one variant into the other. Whether that's the right strategy in this case depends on understanding the particulars of the situation in rather more detail.
What you shouldn't do is to attempt to write one stylesheet that handles both variants. You end up with conditional logic all over the place that clutters your code and makes debugging a nightmare.
But I have seen one alternative approach used successfully: instead of preprocessing the source document to handle the variant vocabulary, preprocess the stylesheet instead.
来源:https://stackoverflow.com/questions/42658497/conflicting-kml-xmlns-attribute-from-kml-to-xslt