Как обрабатывать разные версии файлов xsd в одном приложении Java?

Факты

В моем приложении java мне приходится обрабатывать XML файлы с разными версиями схем (xsd файлы) одновременно. Содержимое XML файлов немного изменилось между разными версиями, поэтому я хотел бы использовать в основном один и тот же код для его обработки и просто делать некоторые случаи, зависящие от версии используемой схемы.

Текущее решение

Сейчас я разбираю XML файлы с помощью анализатора SAX и своего собственного ContentHandler, игнорируя версию схемы, и просто проверяю, нужны ли теги, которые мне нужны для обработки.

Возможная альтернатива

Мне бы очень хотелось использовать JAXB для генерации классов для разбора XML файлов. Таким образом я мог бы удалить все жестко закодированные строки (константы) из моего java-кода и обработать сгенерированные классы.

Вопрос (ы)

  • Как я могу обрабатывать разные версии схемы унифицированным способом с помощью JAXB?
  • Есть ли лучшее решение?

Прогресс

Я скомпилировал версии схемы для разных пакетов v1, v2 и v3. Теперь я могу создать Unmarshaller следующим образом:

JAXBContext jc = JAXBContext.newInstance( 
    v1.Root.class, v2.Root.class, v3.Root.class );
Unmarshaller u = jc.createUnmarshaller();

Теперь u.unmarshal( xmlInputStream ); дает мне класс Root из пакета, соответствующего схеме XML файла.

Далее я попытаюсь определить interface для доступа к общим частям схем. Если вы сделали что-то подобное раньше, сообщите мне. В то же время я читаю спецификации JAXB...

Ответ 1

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

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

Если вы пытаетесь поддержать меняющуюся спецификацию данных, тогда вам нужно ответить на вопрос "как я могу справиться с отсутствующими данными". На это есть несколько ответов: один - поддерживать несколько версий кода. С рефакторингом общей функциональности это не плохая идея, но она может легко стать незаменимой.

Альтернативой является использование одной кодовой базы и своего рода adapter объект, который включает ваши правила. И если вы идете по этому пути, JAXB является неправильным решением, поскольку он привязан к схеме. Возможно, вы сможете использовать разрешающий XML- > Java-конвертер: я верю, что XStream будет работать, и я знаю, что релиз версии Практический XML будет работать (с тех пор как я его написал) - хотя вам придется его самостоятельно создать.

Другая, лучшая альтернатива, в зависимости от сложности схемы, заключается в разработке набора объектов, которые используют XPath для извлечения данных. Я бы, вероятно, реализовал использование "главного" объекта, который содержит выражения XPath для каждого поля в каждом варианте схемы. Затем создайте легкие "оберточные" объекты, которые содержат DOM-версию вашего экземпляра документа и используют XPath, соответствующие схеме. Обратите внимание, однако, что это ограничено доступом только для чтения.