Преобразование файла, совместимого с XML-схемой A, в файл, совместимый с XML-схемой B, с использованием XSLT

Я искал этот вопрос, но кажется чертовски сложно выразить словами проблему, связанную с XSL, поэтому я ничего не придумал.

Проблема у меня такая:

Компания создает приложение, которое использует XML-файлы для хранения своих «документов». Эти файлы применяются к схеме версии 1.1.

Однако компания решает выпустить новую версию программного обеспечения, которая проверяется на соответствие новой схеме с другой структурой, схеме 1.2.

Чтобы клиент мог беспрепятственно использовать новую версию, мы хотим программно преобразовать их файлы, соответствующие версии 1.1, в файлы, соответствующие версии 1.2, при открытии файла. В идеале мы делаем это с помощью XSL-преобразования.

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

Было бы неплохо написать своего рода преобразование, генерирующее преобразование, которое могло бы сопоставлять неизмененные типы из старой схемы в новую и испускать элементы-заполнители (элементы <xsl:message>, например) везде, где это невозможно, чтобы предложите разработчику написать пользовательскую логику вручную там, где это необходимо, с гарантией того, что везде она будет совместима.

Итак, процедура проходит:

  • Запустите Transform A для схемы 1.2. Это генерирует Transform B;
  • Запустите Transform B против схемы 1.1. Это соответствует схеме 1.2 схеме 1.1, где это возможно, создавая Transform C;
  • Преобразование C используется разработчиком в качестве основы для написания надежного преобразования из экземпляра 1.1 в экземпляр 1.2.

Я неплохо реализовал это, но некоторые особенности XSLT 1.0 вызывают у меня проблемы.

Преобразование B требует автоматического создания операторов <xsl:call-template> с указанием типа каждого встречающегося элемента в атрибуте name. Это позволит правильно запустить логику преобразования для каждого типа, чтобы сгенерировать преобразование C.

Однако call-template, похоже, вообще не принимает никакого синтаксиса xpath. Он настаивает на том, что name должен содержать NMTOKEN и только NMTOKEN. Я могу понять это с точки зрения дизайна, но это довольно раздражает, потому что я хочу запускать логику элемента на основе его типа, а не имени. Я хотел бы указать call-template name="@type" внутри шаблона xsl:template match="element". Моя генерация этапа 1 гарантирует, что соответствующий именованный шаблон будет существовать для вызова.

Я не уверен, что делать дальше. Кто-нибудь пробовал что-то подобное раньше? Есть ли какая-то фундаментальная теория информатики, которая заявляет, что это невозможно в декларативном синтаксисе? (Надеюсь нет!)

Надеюсь, мое объяснение понятно. Я отправлю код, если нет.


person Tom W    schedule 17.02.2011    source источник
comment
Одним из решений, которое может оказаться полезным, является создание кода XSLT из самого XSLT с использованием xsl:namespace. -псевдоним. Таким образом, вы сможете предоставлять вещи, которые вы обычно не можете делать во время выполнения, например. вычисление выражения XPath из строк. Хотя dyn:evaluate также можно использовать.   -  person Flack    schedule 17.02.2011
comment
Я не верю, что есть общий способ сделать это.   -  person John Saunders    schedule 18.02.2011
comment
@Tom W: Я думаю, что вы теряете время с таким подходом. Никакая схема не должна быть настолько сложной (и стандарты, конечно же, не являются), что она не позволит вам легко написать преобразование из одной схемы в другую.   -  person    schedule 18.02.2011
comment
@Alejandro: Не знаю, что заставило тебя так сказать. Схемы редко бывают очень сложными, но они длинные. Я говорю из опыта, когда говорю, что поддержание преобразований вручную утомительно. Кроме того, частые изменения версии требуют каждый раз проверять преобразование на глаз.   -  person Tom W    schedule 18.02.2011
comment
@John Saunders: Боюсь, вы ошибаетесь. Я уже получил хороший способ реализовать что-то, что выглядит в целом подходящим. Я просто борюсь с деталями, а также обращаю внимание на подводные камни и сложности.   -  person Tom W    schedule 18.02.2011
comment
@Flack: Спасибо за ваш вклад. Я просмотрел документацию по namespace-alias, но ее полезность не была сразу ясна, поэтому я проигнорировал ее. Однако это может пригодиться для решения некоторых конкретных задач.   -  person Tom W    schedule 18.02.2011


Ответы (1)


Во-первых, на рынке имеется ряд инструментов, которые пытаются генерировать преобразования на основе исходной и целевой схемы, а также графические инструменты для определения взаимосвязи между ними. Лично мне эти инструменты очень не понравились, но некоторым людям они нравятся, так что попробуйте. Примеры можно найти в популярных XML-инструментах, таких как XML Spy и Stylus Studio.

Во-вторых, кажется очень странным пытаться использовать для этого xsl:call-template. Это явно случай преобразования на основе правил с использованием шаблонных правил и xsl:apply-templates. Механизм диспетчеризации, основанный на типе элемента, — это, очевидно, apply-templates, а не call-template. В XSLT 2.0 вы можете делать то, что вы просите, непосредственно с таблицей стилей с поддержкой схемы, которая имеет правила формы

<xsl:template match="element(*, type-name)">

где type-name — это имя типа в схеме.

person Michael Kay    schedule 17.02.2011
comment
Спасибо за ваш вклад. По какой-то причине от меня ускользнула применимость сопоставленных шаблонов к типам, и я до сих пор не совсем уверен в синтаксисе. Должен ли я предположить, что apply-templates select="./@type" будет достаточно? Я не уверен, почему я не получил это. К вашему сведению, я работаю в .Net, который не поддерживает XSLT 2.0. Кроме того, я не думаю, что работодатель, для которого я это изучаю, будет терпеть идею платить за инструменты только для работы с открытыми стандартами, такими как XSL. - person Tom W; 18.02.2011
comment
К сожалению, тот факт, что трудно найти бесплатные процессоры XSLT с поддержкой схем (или вообще процессоры XSLT 2.0), скорее напрямую связан с тем фактом, что многие компании в настоящее время ожидают, что программное обеспечение будет бесплатным. Обидно, но я не буду пытаться превратить это в рекламный ход. - person Michael Kay; 23.02.2011