我可以使用模式强制执行XML属性的顺序吗? 我们的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>

我可以使用模式强制执行XML属性的顺序吗? 我们的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>,xml,performance,xsd,expat-parser,Xml,Performance,Xsd,Expat Parser,这使我们的ProcessAttribute()函数负责读取“键”并决定如何处理该值分析该应用程序表明,大约40%的XML解析时间是按名称/字符串处理这些属性。 如果我能够保证/强制执行属性的顺序(对于初学者来说,ProcessAttribute()中没有字符串比较),那么整个过程可以大大加快。例如,如果“id”属性始终是第一个属性,我们可以直接处理它: void ExpatParser::StartElement(const XML_Char* name, const XML_Char** at

这使我们的
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模式规范,我可以在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模式不支持这种情况-属性只是由名称定义和限制的,例如,它们必须匹配特定的名称-但我不知道如何在XSD中定义这些属性的顺序


我不知道有任何其他方法可以确保XML节点上的属性按特定顺序排列-不确定是否有任何其他XML模式机制(如Schematron或RELAXNG)支持这一点

只是一个猜测,但是您能否尝试将
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>

我想知道,如果允许可选属性,那么解析器的速度是否会变慢,而您的属性似乎总是在那里

再说一次,只是猜测而已

编辑:XML1.0规范说属性顺序不重要


因此,XSD不会执行任何命令。但这并不意味着解析器无法快速工作,因此我将公布上述答案,以防它真正起作用。

我非常确定没有办法在XML文档中强制执行属性顺序。我将假设您可以通过业务流程或其他人为因素(如合同或其他文档)来坚持它

如果您只是假设第一个属性是“id”,并测试名称以确保正确,该怎么办?如果是,则使用该值;如果不是,则可以尝试按名称获取属性,或者丢弃文档


虽然没有按顺序调用属性那么有效,但您可以猜到数据提供程序已将XML交付给spec的次数为非零。其余时间,您可以采取其他行动。

答案是不,唉。我对你40%的数字感到震惊。我发现很难相信把“foo”变成ProcessFoo需要那么长时间。您确定40%不包括执行ProcessFoo所需的时间吗


是否可以使用这个Expat东西按名称访问属性?这是访问属性的更传统的方式。我不是说它会更快,但可能值得一试。

根据xml规范

属性规范在开始标记或空元素标记中的顺序不重要


您可以在

上查看它。我记得,Expat是一个非验证解析器,因此它更适合。。所以你可以放弃XSD的想法。在许多XML方法中,顺序依赖性也不是一个好主意(XSD在当时受到了很多关于元素顺序的批评,例如,MSFT的XML Web服务的赞成者或反对者)

进行自定义编码,只需扩展逻辑以实现更高效的查找或深入解析器源代码。编写关于编码高效替换的工具,同时屏蔽软件代理和用户,这是很简单的。。您希望这样做,以便在保持向后兼容性和可逆性的同时轻松迁移。此外,请使用固定大小约束/属性名称转换

(考虑使用ExpAT:幸运)和它的原始速度。想象CLR DEVS如何爱XML缩放工具,他们通常在“只查询数据库”的过程中发送200毫巴….. [P/>>P> XML属性没有顺序,因此没有强制执行的顺序。< / P>


如果您想要有序的东西,就需要XML元素。或者与XML不同的东西。例如,JSON、YAML和bEncode都有映射(无序)和序列(有序)。

正如其他人所指出的,不,不能依赖属性排序


如果我有任何涉及2500个XML文件和150万个键/值对的过程,我会尽快将这些数据从XML中提取出来,并转换成更有用的形式。数据库、二进制序列化格式等等。使用XML(模式验证除外)没有任何好处。每次我得到一个新的XML文件时,我都会更新我的存储,并将解析150万个XML元素从我的流程的主流中去除。

“Expat thing”是速度最快的解析器之一。。不要感到震惊,你刚刚被微软和IBM出售了XML,但它并没有扩展:-)加里,你是对的。我没有详细说明processAttribute()函数的具体功能,因为我认为它与原始问题无关。。。我们在应用程序启动时解析这些XML文档,并将元素数据转储到sqlite数据库中以供以后处理。sqlite API允许通过索引绑定参数——因此,如果我能够确信XML属性始终与Insert语句中的参数顺序相同,那么事情会发展得更快。这不是XML模式的限制,而是XML本身的限制。请参阅st.stoqnov的评论。为什么要使用属性而不是Foo1Foo110这是描述?您可以指定
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.
}
<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>
<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>