Подтвердить что ты не робот

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

Наше приложение С++ считывает данные конфигурации из файлов 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" ... />

Чтобы быстро выполнить этот процесс, мы используем Expat для анализа 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-документе? Если ответ "нет" - может ли кто-нибудь, возможно, предложить альтернативу, которая не имела бы огромного времени исполнения?

4b9b3361

Ответ 1

В соответствии со спецификацией xml,

порядок спецификаций атрибутов в теге start-tag или теге элемента не значителен

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

Ответ 2

XML-атрибуты не имеют порядка, поэтому нет порядка для обеспечения соблюдения.

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

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

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

Ответ 7

Просто догадайтесь, но можете ли вы попробовать добавить 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>

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

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

EDIT: Спецификация XML 1.0 указывает, что порядок атрибутов не имеет значения. http://www.w3.org/TR/REC-xml/#sec-starttags

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

Ответ 8

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

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

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