У меня есть нестандартная XML-схема, которая развивается: элементы добавляются, другие удаляются, а пространство имен изменяется в соответствии с новой версией (например, с "http://foo/1.0" на" http://foo/1.1"). Я хочу написать XSLT, который преобразуетXML-документы из старой схемы в новую. Моя первая попытка работает, но она многословна и не масштабируется, и мне нужна помощь в ее уточнении.
Вот пример документа для схемы 1.0:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo:rootElement xmlns:foo="http://foo/1.0">
<obsolete>something</obsolete>
<stuff>
<alpha>a</alpha>
<beta>b</beta>
</stuff>
</foo:rootElement>
В схеме 1.1 устаревший элемент исчезает, но все остальное остается, поэтому XSLT нужно сделать две вещи:
- Удалить тег
- Изменить пространство именот http://foo/1.0 до http://foo/1.1
Вот мое решение:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:foo1="http://foo/1.0"
xmlns:foo="http://foo/1.1"
exclude-result-prefixes="foo1">
<xsl:output method="xml" standalone="yes" indent="yes"/>
<!-- Remove the "obsolete" tag -->
<xsl:template match="foo1:rootElement/obsolete"/>
<!-- Copy the "alpha" tag -->
<xsl:template match="foo1:rootElement/stuff/alpha">
<alpha>
<xsl:apply-templates/>
</alpha>
</xsl:template>
<!-- Copy the "beta" tag -->
<xsl:template match="foo1:rootElement/stuff/beta">
<beta>
<xsl:apply-templates/>
</beta>
</xsl:template>
<!-- Copy the "stuff" tag -->
<xsl:template match="foo1:rootElement/stuff">
<stuff>
<xsl:apply-templates/>
</stuff>
</xsl:template>
<!-- Copy the "rootElement" tag -->
<xsl:template match="foo1:rootElement">
<foo:rootElement>
<xsl:apply-templates/>
</foo:rootElement>
</xsl:template>
</xsl:stylesheet>
Хотя это дает желаемый результат, обратите внимание, что у меня есть шаблон копирования для каждогоэлемент в схеме: альфа, бета и т. д. Для сложных схем с сотнями видов элементов мне нужно было бы добавить сотни шаблонов!
Я думал, что смогу устранить эту проблему, сократив количество копий.Mplates в одно преобразование идентичности, как это:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:foo1="http://foo/1.0"
xmlns:foo="http://foo/1.1"
exclude-result-prefixes="foo1">
<xsl:output method="xml" standalone="yes" indent="yes"/>
<xsl:template match="foo1:rootElement/obsolete"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="foo1:rootElement/stuff">
<xsl:copy>
<xsl:call-template name="identity"/>
</xsl:copy>
</xsl:template>
<xsl:template match="foo1:rootElement">
<foo:rootElement>
<xsl:apply-templates/>
</foo:rootElement>
</xsl:template>
</xsl:stylesheet>
Но он выдает:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo:rootElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:foo="http://foo/1.1">
<stuff xmlns:foo="http://foo/1.0">
<stuff>
<alpha>a</alpha>
<beta>b</beta>
</stuff>
</stuff>
</foo:rootElement>
Элемент "материал" был скопирован, что я хочу, но он обернут вдругой элемент «вещи», помеченный старым пространством имен.Я не понимаю, почему это происходит.Я пробовал много способов исправить это, но безуспешно.Какие-либо предложения?Спасибо.