<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文件(即超过150万个键/值属性对)。这些XML文件来自许多不同的来源/团队,并根据模式进行验证。但是,有时节点看起来像这样:
<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()
函数需要负责读取“key”,并决定如何处理该值。应用程序的分析显示,约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模式规范,我可以在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文档中属性的顺序?如果答案是“否”,是否有人可以建议一种替代方案,而不会带来巨大的运行时性能损失?