Могу ли я обеспечить порядок атрибутов XML с помощью схемы?

StackOverflow https://stackoverflow.com/questions/1682131

Вопрос

Наше приложение C++ считывает данные конфигурации из XML-файлов, которые выглядят примерно так:

<data>
 <value id="FOO1" name="foo1" size="10" description="the foo" ... />
 <value id="FOO2" name="foo2" size="10" description="the other foo" ... />
 ...
 <value id="FOO300" name="foo300" size="10" description="the last foo" ... />
</data>

Полная конфигурация приложения состоит примерно из 2500 таких XML-файлов (что соответствует более чем 1,5 миллионам пар атрибутов ключ/значение).XML-файлы поступают из разных источников/команд и проверяются на соответствие схеме.Однако иногда <value/> узлы выглядят так:

<value name="bar1" id="BAR1" description="the bar" size="20" ... />

или это:

<value id="BAT1" description="the bat" name="bat1"  size="25" ... />

Чтобы ускорить этот процесс, мы используем Эмигрант для анализа XML-документов.Expat предоставляет атрибуты в виде массива — вот так:

void ExpatParser::StartElement(const XML_Char* name, const XML_Char** atts)
{
 // The attributes are stored in an array of XML_Char* where:
 //  the nth element is the 'key'
 //  the n+1 element is the value
 //  the final element is NULL
 for (int i = 0; atts[i]; i += 2) 
 {
  std::string key = atts[i];
  std::string value = atts[i + 1];
  ProcessAttribute (key, value);
 }
}

Это возлагает всю ответственность на нас. ProcessAttribute() функция для чтения «ключа» и решения, что делать со значением. Профилирование приложения показало, что около 40% общего времени синтаксического анализа XML приходится на эти атрибуты по имени/строке.

Весь процесс можно было бы значительно ускорить, если бы я мог гарантировать/обеспечивать соблюдение порядка атрибутов (во-первых, никаких сравнений строк в ProcessAttribute()).Например, если атрибут 'id' был всегда с первым атрибутом мы могли бы справиться напрямую:

void ExpatParser::StartElement(const XML_Char* name, const XML_Char** atts)
{
 // The attributes are stored in an array of XML_Char* where:
 //  the nth element is the 'key'
 //  the n+1 element is the value
 //  the final element is NULL
 ProcessID (atts[1]);
 ProcessName (atts[3]);
 //etc.
}

Согласно спецификациям схемы W3C, я могу использовать <xs:sequence> в схеме XML для обеспечения порядка элементов - но, похоже, это не работает для атрибутов - или, возможно, я использую его неправильно:

<xs:element name="data">
 <xs:complexType>
  <xs:sequence>
   <xs:element name="value" type="value_type" minOccurs="1" maxOccurs="unbounded" />
  </xs:sequence>
 </xs:complexType>
</xs:element>

<xs:complexType name="value_type">
 <!-- This doesn't work -->
 <xs:sequence>
  <xs:attribute name="id" type="xs:string" />
  <xs:attribute name="name" type="xs:string" />
  <xs:attribute name="description" type="xs:string" />
 </xs:sequence>
</xs:complexType>

Есть ли способ обеспечить порядок атрибутов в документе XML?Если ответ «нет», может ли кто-нибудь предложить альтернативу, которая не повлечет за собой огромное снижение производительности во время выполнения?

Это было полезно?

Решение

Согласно спецификации xml,

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

Вы можете проверить это на раздел 3.1

Другие советы

Атрибуты XML не иметь приказ, следовательно, приказа для исполнения нет.

Если вы хотите что-то упорядочить, вам нужны элементы XML.Или что-то отличное от XML.JSON, YAML и bEncode, например.имеют как карты (неупорядоченные), так и последовательности (упорядоченные).

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

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

Ответ является нет, увы.Я в шоке от вашей цифры 40%.Мне трудно поверить, что превращение «foo» в ProcessFoo занимает так много времени.Вы уверены, что в эти 40% не входит время, затраченное на выполнять ПроцессФу?

Можно ли получить доступ к атрибутам по имени, используя эту вещь Expat?Это более традиционный способ доступа к атрибутам.Я не говорю, что это будет быстрее, но, возможно, стоит попробовать.

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

Я не знаю другого способа убедиться, что атрибуты узла XML идут в определенном порядке - не уверен, что какой-либо из других механизмов схемы XML, таких как Schematron или Relax NG, будет поддерживать это....

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

Что, если вы просто предположили, что первым атрибутом был «id», и проверили имя, чтобы убедиться в этом?Если да, используйте значение, если нет, то можно попробовать получить атрибут по имени или выкинуть документ.

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

Это всего лишь предположение, но можете ли вы попробовать добавить use="required" для каждой из ваших спецификаций атрибутов?

<xs:complexType name="value_type">
 <!-- This doesn't work -->
 <xs:sequence>
  <xs:attribute name="id" type="xs:string" use="required" />
  <xs:attribute name="name" type="xs:string" use="required" />
  <xs:attribute name="description" type="xs:string" use="required" />
 </xs:sequence>
</xs:complexType>

Мне интересно, замедляется ли анализатор из-за разрешения дополнительных атрибутов, когда они появятся, ваши атрибуты всегда будут там.

Опять же, просто предположение.

РЕДАКТИРОВАТЬ: Спецификация XML 1.0 гласит, что порядок атрибутов не имеет значения. http://www.w3.org/TR/REC-xml/#sec-starttags

Следовательно, XSD не будет обеспечивать соблюдение какого-либо порядка.Но это не значит, что парсеры нельзя обмануть и заставить работать быстро, поэтому я оставляю приведенный выше ответ опубликованным на случай, если он действительно сработает.

Насколько я помню, Expat — это парсер без проверки, и он лучше для него.так что вы, вероятно, можете отказаться от этой идеи XSD.Зависимость от порядка также не является хорошей идеей во многих XML-подходах (XSD в свое время неоднократно подвергался критике за порядок элементов, например, со стороны сторонников и противников XML Web Services в MSFT).

Выполните свою собственную кодировку и просто расширьте свою логику для более эффективного поиска или покопайтесь в исходном коде синтаксического анализатора.Написать инструментарий для эффективной замены кодирования, одновременно защищая от него программных агентов и пользователей, нетрудно.вы хотите сделать это так, чтобы его можно было легко перенести, сохранив при этом обратную совместимость и обратимость.Кроме того, используйте ограничения фиксированного размера/перевод имени атрибута.

[Считайте, что вам повезло с Expat :) и его невероятной скоростью.Представьте себе, как разработчики CLR любят возможности масштабирования XML: они регулярно отправляют по сети 200 МБ в процессе «простого запроса к базе данных»...]

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top