Конфликт атрибута 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>
Это не работает, и я предполагаю, что это потому, что для атрибута 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"
Я чувствую, что ответ будет глупо простым, но я еще не наткнулся на него, и у меня заканчиваются вещи, чтобы попробовать Google. Что вы, ребята, предлагаете?
2 ответа
Важно понимать, что префиксы пространства имен XML не имеют смысла. Они являются просто формой сокращения имен пространств имен, которые представляют собой URI, идентифицирующие пространства имен. Это имя пространства имен, связанное с префиксом посредством атрибута объявления пространства имен, которое фактически идентифицирует пространство имен и определяет области имен в XML-процессоре с поддержкой пространства имен, таком как XSLT-процессор. Таким образом, нет смысла пытаться привязать один префикс к двум альтернативным именам пространства имен.
Ничто из этого не имеет никакого отношения к расположению документов схемы XML. Предположим, однако, что KML 2.2, о котором вы говорите, описан в документе схемы по адресу http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd, его имя пространства имен http://www.opengis.net/kml/2.2
, что прямо указано в его схеме. Документы экземпляров не могут использовать другое имя пространства имен (хотя они могут связывать любой префикс пространства имен, который они хотят, с этим именем - это не обязательно должен быть "kml").
Итог: есть только две возможности:
Документ, предоставленный вашим клиентом, искажен из-за неправильного имени пространства имен. В этом случае лучше всего исправить имя пространства имен в файле клиента или попросить клиента сделать это. Вы можете сделать это, отредактировав его, или вы можете написать таблицу стилей для выполнения такого преобразования. В любом случае, было бы неплохо проверить полученный документ по схеме, которой, как вы ожидаете, он будет соответствовать.
Документ, предоставленный вашим клиентом, относится к другому типу XML-документа (в широком смысле), чем вы ожидаете, и готов обработать его. В этом случае единственное, что нужно сделать, это запросить у клиента новый файл правильного типа.
Пространство имен Google является расширением стандарта KML: см. https://developers.google.com/kml/documentation/kmlreference
Поэтому, если вы просто измените свою таблицу стилей для обработки другого пространства имен, она может работать или не работать, в зависимости от (a) того, действительно ли используются расширения Google, и (b) насколько надежно была написана таблица стилей для обработки расширений (шаблон правила, которые отбрасывают любой элемент, имеющий пустой текст или пустой атрибут, не выглядят особенно хорошим началом.)
Обычно мой совет, когда у вас есть два варианта словаря XML с использованием разных пространств имен, - начинать с предварительной обработки одного варианта в другом. Правильно ли выбрана стратегия в этом случае, зависит от более подробного понимания ситуации.
Чего не следует делать, так это пытаться написать одну таблицу стилей, которая обрабатывает оба варианта. Вы получаете условную логику повсюду, которая загромождает ваш код и делает отладку кошмаром.
Но я видел, как успешно использовался один альтернативный подход: вместо предварительной обработки исходного документа для обработки альтернативного словаря, вместо этого выполняется предварительная обработка таблицы стилей.