问题
I am able to access the<trkpt></trkpt>
nodes by the xpath expression<xsl:for-each select='gpx/trk/trkseg/trkpt'>
when the GPX file has the following simple structure:
<gpx>
<trk>
<trkseg>
<trkpt lat="50.5324906" lon="7.0842605">
<ele>105.8824463</ele>
<time>2010-07-11T08:50:16Z</time>
</trkpt>
<trkpt lat="50.5323745" lon="7.0843524">
<ele>108.7662354</ele>
<time>2010-07-11T08:50:44Z</time>
</trkpt>
...
</trkseg>
</trk>
</gpx>
How can i achieve the same effect when namespaces are involved, e.g.:
<gpx xmlns="http://www.topografix.com/GPX/1/1"
creator="MapSource 6.15.11"
version="1.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1
http://www.topografix.com/GPX/1/1/gpx.xsd">
回答1:
In XSLT 1.0:
<xsl:apply-templates
select="/g:gpx/g:trk/g:trkseg/g:trkpt"
xmlns:g="http://www.topografix.com/GPX/1/1"/>
In XSLT 2.0:
<xsl:apply-templates
select="/gpx/trk/trkseg/trkpt"
xpath-default-namespace="http://www.topografix.com/GPX/1/1"/>
So, you need to declare the namespace (prefix, URI) in your stylesheet and add this namespace in your QName test of XPath expression.
As example, this XSLT 1.0 stylesheet:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:g="http://www.topografix.com/GPX/1/1">
<xsl:output method="text"/>
<xsl:template match="g:trkpt">
<xsl:text>Found 'trkseg' element
</xsl:text>
</xsl:template>
</xsl:stylesheet>
And this XSLT 2.0 stylesheet:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://www.topografix.com/GPX/1/1">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="trkpt">
<xsl:text>Found 'trkseg' element
</xsl:text>
</xsl:template>
</xsl:stylesheet>
With this input:
<gpx xmlns="http://www.topografix.com/GPX/1/1"
creator="MapSource 6.15.11"
version="1.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1
http://www.topografix.com/GPX/1/1/gpx.xsd">
<trk>
<trkseg>
<trkpt lat="50.5324906" lon="7.0842605">
<ele>105.8824463</ele>
<time>2010-07-11T08:50:16Z</time>
</trkpt>
<trkpt lat="50.5323745" lon="7.0843524">
<ele>108.7662354</ele>
<time>2010-07-11T08:50:44Z</time>
</trkpt>
</trkseg>
</trk>
</gpx>
Both output:
Found 'trkseg' element
Found 'trkseg' element
回答2:
The thing to remember is that a default namespace is not the same as a null namespace, and in xslt, not specifying a namespace in a path is a null namespace, NOT the default. ( The default namespace would be in effect for literals though, I believe. ) So in your xsl stylesheet, you need to specify the GPX namespace with a prefix and use that prefix in your paths:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:gpx="http://www.topografix.com/GPX/1/1" >
<xsl:template match="/">
<xsl:for-each select='gpx:gpx/gpx:trk/gpx:trkseg/gpx:trkpt'>
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
You can also match using functions like local-name() in the path:
select='//*[local-name(.)="trkpt"]'
but generally it's better to use explicit namespaces.
来源:https://stackoverflow.com/questions/3364825/xpath-query-for-gpx-files-with-namespaces