Можно ли перегружать элемент XSD несколькими возможными сложными типами? - PullRequest
7 голосов
/ 07 июля 2011

У меня есть схема, определяющая запись event , которая используется для передачи сообщения между двумя системами в сценарии публикации / подписки. Событие включает в себя элемент «payload», event_data , с подробностями сообщения. Сложность состоит в том, что полезная нагрузка может быть любого из 30+ типов , каждый из которых определен в своем собственном XSD.

Например (урезанный):

<event>
   <event_name>new_phone_number</event_name>
   <event_data>
      <areacode>303</areacode>
      <number>555-1212</number>
      <extension>31</extension>
   </event_data>
</event>

В этом случае event_data имеет тип phone_number , который определен в другом месте в импортированном XSD. Но я хочу использовать тот же механизм для переноса других видов структурированных данных сообщений. Например, может быть, это событие смены работы, определяемое как тип job_details :

<event>
   <event_name>new_job</event_name>
   <event_data>
      <job_title>CEO</job_title>
      <start_date>01/01/2012</start_date>
      <location>Main Office</location>
   </event_data>
</event>

Внутренняя запись, хранящаяся в элементе event_data , имеет тип job_details , как определено в импортированном XSD. «Внешняя» запись типа event - это не более чем способ переноса полезной нагрузки, содержащейся во «внутренней» записи.

До сих пор я рассмотрел три способа атаки, каждый с проблемами:

  1. Используйте конструкцию выбора, в которой перечислены все возможные типы записей. Кажется, проблема в том, что xml / xsd не является естественным, когда все записи в списке выбора имеют одинаковое имя элемента.

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

  3. Кто-то ответил на аналогичный вопрос, предложив использовать объединение - но, похоже, это применимо только к простым типам. Не будет охватывать мой случай использования.

Тупик! Любое руководство?

Ответы [ 3 ]

1 голос
/ 07 июля 2011

В XSD 1.1 (реализовано в Xerces и Saxon) вы можете сделать это с помощью функции, называемой «условное присвоение типа», посредством чего на уровне объявления элемента вы выбираете, какой тип использовать из списка альтернатив, выбранных путем применениявыражение XPath для атрибутов элемента.

1 голос
/ 07 июля 2011

Вы можете сделать это, используя переопределение xsi:type в вашем экземпляре документа. Процессоры XML не могут «выводить» типы, вы должны предоставить это. Пример:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <event>
     <event_name>new_phone_number</event_name>
     <event_data xsi:type="PhoneNumberData">
        <areacode>303</areacode>
        <number>555-1212</number>
        <extension>31</extension>
     </event_data>
  </event>
</root>

Обратите внимание, что вы должны определить базовый комплексный тип EventData, и PhoneNumberData должен быть производным от него, чтобы это работало.

0 голосов
/ 11 июля 2011

Можно также использовать группы подстановки , хотя это, вероятно, не соответствует вашей проблеме, а также двум ранее предложенным.Группы подстановки больше похожи на «использование определенного элемента вместо универсального элемента», тогда как ваша проблема больше похожа на «использование определенного типа вместо универсального типа».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...