【问题标题】:Conflicting KML xmlns attribute from KML to XSLT从 KML 到 XSLT 的冲突 KML xmlns 属性
【发布时间】:2017-03-07 21:15:43
【问题描述】:

我有一个 XSLT,它负责将 KML 重新格式化为 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>

通常我们的客户给我们的 KML 文件都有这样的 kml 开始标签:

<kml xmlns="http://www.opengis.net/kml/2.2">

对于这种情况,XSLT 可以很好地转换该 KML 文件。但是我们今天得到了一个...

<kml xmlns="http://earth.google.com/kml/2.2">...</kml>

这不起作用,我认为这是因为 KMLs xmlns 属性未设置为:http://www.opengis.net/kml/2.2,或者 XSLTs xmlns:kml 未设置为:http://earth.google.com/kml/2.2

我尝试了以下方法,但没有成功

xmlns:kml="http://www.opengis.net/kml/2.2 http://earth.google.com/kml/2.2" 

我觉得答案会非常简单,但我还没有偶然发现它,我已经没有东西可以尝试和谷歌了。你们有什么建议?

【问题讨论】:

  • 你确定唯一的区别是命名空间吗?如果是这样,请考虑编写第一个样式表或样式表步骤,将命名空间规范化为您所期望的。
  • 请显示来自您的处理器的 XSLT 错误,因为 这不起作用 没有帮助。

标签: xslt kml google-earth gml opengis


【解决方案1】:

了解 XML 名称空间前缀本身并不有意义,这一点很重要。它们只是命名空间名称的一种简写形式,命名空间名称是标识命名空间的 URI。正是命名空间 name,通过命名空间声明属性绑定到前缀,它实际标识命名空间感知 XML 处理器(例如 XSLT 处理器)中的命名空间和范围名称。因此,尝试将一个前缀绑定到两个备用命名空间名称是没有意义的。

这些都与 XML 模式文档的 位置 无关。但是,假设您正在谈论的 KML 2.2 是架构文档 http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd 所描述的 KML 2.2,其命名空间名称为 http://www.opengis.net/kml/2.2,正如其架构明确指定的那样。实例文档不能随意使用不同的命名空间名称(尽管它们可以随意将他们想要的任何命名空间前缀绑定到该名称——它不必是“公里”)。

底线:只有两种可能:

  1. 由于使用了错误的命名空间名称,您的客户端提供的文档格式不正确。在这种情况下,最好的办法是修复客户端文件中的命名空间名称,或者要求客户端这样做。您可以通过编辑它来做到这一点,或者您可以编写一个样式表来执行这样的转换。无论哪种方式,根据您希望它符合的架构验证生成的文档可能是一个好主意。

  2. 您的客户端提供的文档与您预期的 XML 文档类型(松散意义上的)不同,并且已准备好处理。在这种情况下,唯一要做的就是向客户端请求一个正确类型的新文件。

【讨论】:

    【解决方案2】:

    Google 的命名空间是 KML 标准的扩展:请参阅 https://developers.google.com/kml/documentation/kmlreference

    因此,如果您只是简单地更改样式表来处理不同的命名空间,它可能会或可能不会起作用,这取决于 (a) 是否实际使用了 Google 扩展,以及 (b) 为处理扩展而编写的样式表有多健壮(丢弃任何具有空文本或空属性的元素的模板规则看起来并不是一个特别好的开始。)

    一般来说,当您有两个使用不同名称空间的 XML 词汇表变体时,我的建议是首先将一个变体预处理到另一个变体中。在这种情况下,这是否是正确的策略取决于更详细地了解情况的细节。

    您不应该尝试编写一个样式表来处理这两种变体。您最终会得到到处都是条件逻辑,这会使您的代码变得混乱并使调试成为一场噩梦。

    但我已经看到一种成功使用的替代方法:不是预处理源文档来处理变体词汇,而是预处理样式表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多