Наше приложение С++ считывает данные конфигурации из файлов 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-документе? Если ответ "нет" - может ли кто-нибудь, возможно, предложить альтернативу, которая не имела бы огромного времени исполнения?