Использовать родительский XML-элемент в качестве контейнера для повторяющихся дочерних элементов?

предположим, вы хотите, чтобы какой-то конкретный элемент XML произошел 0+ раз. Например,<record> элемент может встречаться несколько раз:

<repository>
  <record>Record 1</record>
  <record>Record 2</record>
  <record>Record 3</record>
</repository>

существуют ли какие-либо веские причины для включения родительского элемента в качестве контейнера для них? Например, следующее использует <recordSet> элемент для содержания <record> элементы:

<repository>
  <recordSet>
    <record>Record 1</record>
    <record>Record 2</record>
    <record>Record 3</record>
  </recordSet>
</repository>

Я попытался найти любые связанные вопросы, прежде чем ставить это, поэтому мои извинения, если это уже было задано. Спасибо заранее за любую информацию!


редактировать - 22 июля 2009:

спасибо всем за отличные отзывы! (Я бы прокомментировал / проголосовал за людей, но у меня пока недостаточно очков репутации.) Я, вероятно, продолжу этот маршрут, и я также хотел поблагодарить @16bytes за их совет, в том числе просто назвать родителя, используя множественное число повторяющихся дочерних элементов.

4 ответов


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

кроме этого, допустимо опустить родительский элемент и сделать файл заметно менее подробным.

в вашей первый пример, пользовательский элемент может быть смешан с записями, это допустимо, но это может быть трудно определить:

<repository>
  <record>Record 1</record>
  <record>Record 2</record>
  <user>Bill</user>
  <record>Record 3</record>
</repository>

тогда как с окружающим элементом вы можете разделить коллекцию и иметь несколько экземпляров этой коллекции:

<repositories>
  <users>
    <user>Bill</user>
  </users>
  <repository>
    <id>id1</id>
    <recordSet>
      <id>recordSet1</id>
      <record>Record 1</record>
      <record>Record 2</record>
      <record>Record 3</record>
    </recordSet>
    <recordSet>
      <id>recordSet2</id>
      <record>Record 1</record>
      <record>Record 2</record>
      <record>Record 3</record>
    </recordSet>
  </repository>
  <repository>
    <id>id2</id>
    <recordSet>
      <record>Record 1</record>
      <record>Record 2</record>
      <record>Record 3</record>
    </recordSet>
  </repository>
</repositories>

вы наткнулись на второе из моих правил руководства по дизайну XML (первое-использовать атрибуты только для идентификаторов и реальные метаданные, третье существо не использует пространства имен, если вы не знаете, что делаете), которые я пытаюсь использовать при разработке xml-документов. В дополнение к хорошему эмпирическому правилу, он также делает ваш документ:

  • легче моделировать в XML-схеме или других языках проверки
    • также легче повторно использовать сложный тип
  • легче читать (IMHO)
  • легче для пользователей grok при прохождении документа
  • (выше) легче привязать к объекту ООП по вашему выбору

одно предложение, я бы попробовал:

<Root>
   <Items>
     <Item>a</Item>
     <Item>b</Item>
     <Item>c</Item>
   </Items>
</Root>

более простой суффикс "s" более лаконичен и легче запоминается и применяется. Если вы используете общее существительное коллекции, вы или коллега забудете, какое из них в конечном итоге, поэтому вы увидите наборы, смешанные со списками с контейнерами. Но это больше стиль, чем хорошая практика, и я не хочу начинать религиозные войны ;)

(Апперкамель для элементов!, lowerCamel для атрибутов! -- извините)


хотя у меня также есть инстинктивное предпочтение для обернутых коллекций, интересно отметить, что Google другое мнение.

XML-элементы, которые просто обернуть повторяющиеся дочерние элементы не должны использоваться. [Обоснование: они не используются в Atom и ничего не добавляют.]


это полезно, если в вашей <repository> вы хотите разрешить несколько <recordSet> элементы:

<repository>
  <recordSet id="1">
    <record>Record 1</record>
    <record>Record 2</record>
    <record>Record 3</record>
  </recordSet>
  <recordSet id="2">
    <record>Record 2.1</record>
    <record>Record 2.2</record>
    <record>Record 2.3</record>
  </recordSet>
</repository>