【问题标题】:XPath query for GPX files with namespaces?带有名称空间的 GPX 文件的 XPath 查询?
【发布时间】:2011-03-22 20:16:55
【问题描述】:

当 GPX 文件具有以下简单结构时,我可以通过 xpath 表达式<xsl:for-each select='gpx/trk/trkseg/trkpt'> 访问<trkpt></trkpt>节点:

<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>

涉及命名空间时如何实现相同的效果,例如:

<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">

【问题讨论】:

    标签: xslt xpath gpx


    【解决方案1】:

    在 XSLT 1.0 中:

    <xsl:apply-templates 
        select="/g:gpx/g:trk/g:trkseg/g:trkpt"
        xmlns:g="http://www.topografix.com/GPX/1/1"/> 
    

    在 XSLT 2.0 中:

    <xsl:apply-templates 
        select="/gpx/trk/trkseg/trkpt" 
        xpath-default-namespace="http://www.topografix.com/GPX/1/1"/> 
    

    因此,您需要在样式表中声明命名空间(前缀、URI)并将此命名空间添加到 XPath 表达式的 QName 测试中。

    例如,这个 XSLT 1.0 样式表:

    <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&#xA;</xsl:text>
        </xsl:template>
    </xsl:stylesheet>
    

    还有这个 XSLT 2.0 样式表:

    <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&#xA;</xsl:text>
        </xsl:template>
    </xsl:stylesheet>
    

    有了这个输入:

    <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>
    

    两个输出:

    Found 'trkseg' element
    Found 'trkseg' element
    

    【讨论】:

    • @Flack:谢谢!这让我变得漂亮了一点。
    【解决方案2】:

    要记住的是,默认命名空间与空命名空间不同,在 xslt 中,不在路径中指定命名空间是空命名空间,而不是默认命名空间。 (我相信默认命名空间对文字有效。) 因此,在您的 xsl 样式表中,您需要使用前缀指定 GPX 命名空间 并在路径中使用该前缀:

    <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>
    

    还可以在路径中使用 local-name() 等函数进行匹配:

    select='//*[local-name(.)="trkpt"]'
    

    但通常最好使用显式命名空间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-24
      • 2011-11-07
      • 2011-01-05
      • 2012-01-23
      相关资源
      最近更新 更多