Конфликтующий атрибут KML xmlns из KML в XSLT

У меня есть 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>

Это не работает, и я предполагаю, что это связано с тем, что для атрибута xmlns KML не установлено значение: http://www.opengis.net/kml/2.2 или XSLT 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" 

Я чувствую, что ответ будет до глупости простым, но я еще не наткнулся на него, и у меня заканчиваются вещи, чтобы попробовать и Google. Что вы предлагаете, ребята?


person Jeshicat    schedule 07.03.2017    source источник
comment
Вы уверены, что разница только в пространстве имен? Если это так, подумайте о том, чтобы написать первую таблицу стилей или шаг таблицы стилей, который нормализует пространство имен до того, которое вы ожидаете.   -  person Martin Honnen    schedule 08.03.2017
comment
Пожалуйста, покажите ошибку XSLT от вашего процессора, так как это не работает не помогает.   -  person Parfait    schedule 08.03.2017


Ответы (2)


Важно понимать, что префиксы пространств имен XML не имеют смысла по своей сути. Они являются просто формой сокращения имен пространств имен, которые представляют собой URI, идентифицирующие пространства имен. Именно пространство имен name, связанное с префиксом через атрибут объявления пространства имен, фактически идентифицирует пространство имен и имена областей действия в XML-процессоре, поддерживающем пространство имен, таком как XSLT-процессор. Таким образом, нет смысла пытаться связать один префикс с двумя альтернативными именами пространств имен.

Ничто из этого не имеет ничего общего с местоположением документов XML-схемы. Предположим, однако, что KML 2.2, о котором вы говорите, описан в документе схемы по адресу http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd, его имя пространства имен — http://www.opengis.net/kml/2.2, как явно указано в его схеме. Документы-экземпляры не имеют права использовать другое имя пространства имен (хотя они могут привязывать к этому имени любой префикс пространства имен, какой захотят). быть "кмл").

Итог: есть только два варианта:

  1. Документ, предоставленный вашим клиентом, искажен в результате использования неправильного имени пространства имен. В этом случае лучше всего исправить имя пространства имен в файле клиента или попросить сделать это клиента. Вы можете сделать это, отредактировав его, или вы можете написать таблицу стилей для выполнения такого преобразования. В любом случае, может быть хорошей идеей проверить полученный документ на соответствие схеме, которой вы ожидаете, что он будет соответствовать.

  2. Документ, предоставленный вашим клиентом, имеет другой тип XML-документа (расплывчатый смысл), чем вы ожидаете, и готовы к работе. В этом случае остается только запросить у клиента новый файл нужного типа.

person John Bollinger    schedule 07.03.2017

Пространство имен Google является расширением стандарта KML: см. https://developers.google.com/kml/documentation/kmlreference

Таким образом, если вы просто измените свою таблицу стилей для работы с другим пространством имен, она может работать или не работать в зависимости от того, (а) действительно ли используются расширения Google, и (б) насколько надежно написана таблица стилей для обработки расширений (шаблон правила, которые отбрасывают любой элемент с пустым текстом или пустым атрибутом, не выглядят особенно хорошим началом.)

Как правило, мой совет, когда у вас есть два варианта словаря XML, использующих разные пространства имен, состоит в том, чтобы начать с предварительной обработки одного варианта в другой. Является ли это правильной стратегией в данном случае, зависит от более подробного понимания особенностей ситуации.

Чего вам не следует делать, так это пытаться написать одну таблицу стилей, которая обрабатывает оба варианта. Вы в конечном итоге получаете условную логику повсюду, которая загромождает ваш код и превращает отладку в кошмар.

Но я видел один успешно используемый альтернативный подход: вместо предварительной обработки исходного документа для обработки словаря вариантов предварительно обработайте таблицу стилей.

person Michael Kay    schedule 08.03.2017