2009-11-05 30 views
17

我們的C++應用程序讀取XML文件看起來像這樣的配置數據:這些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(換算成150多萬的鍵/值屬性對) 。 XML文件來自許多不同的來源/團隊,並根據模式進行驗證。但是,有時<value/>節點是這樣的:

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

或本:

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

爲了使這個過程快,我們正在使用Expat解析XML文檔。外籍公開的屬性數組 - 像這樣:

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文檔中的屬性順序?如果答案是「否」 - 任何人都可能提出一個不會帶來巨大運行時性能損失的替代方案嗎?

+2

你爲什麼去與屬性,而不是 FOO1 foo1這是描述?你可以指定元素的順序,爲什麼不使用它們? – jmucchiello 2009-11-06 01:15:38

+0

+1這是一個寫得很好(有趣)的問題。 – 2012-09-14 18:26:03

回答

30

根據XML規範,

在起始標籤或空元素標籤屬性規格的順序並不顯著

您可以在section 3.1

1

我不認爲XML Schema支持 - 屬性只是由名稱來定義和限制,例如,他們必須匹配一個特定的名字 - 但我看不出如何在XSD中爲這些屬性定義一個訂單。

我不知道有任何其他方式來確保XML節點上的屬性按照特定的順序進來 - 不確定是否有像Schematron或Relax NG這樣的其他XML架構機制會支持這種機制....

+4

這不是XML模式的限制,而是XML本身的限制。參見st.stoqnov的評論。 – porges 2009-11-05 17:45:13

0

只是一個猜測,但是您可以嘗試將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不會強制執行任何命令。但這並不意味着解析器不能很快被愚弄到工作中,所以我會保留上面的答案以防其實際工作。

1

我很確定沒有辦法強制XML文檔中的屬性順序。我會假設你可以通過業務流程或其他人爲因素,如合同或其他文件來堅持。

如果你只是假定第一個屬性是「ID」,並測試了名稱以確保該怎麼辦?如果是,請使用該值,如果不是,則可嘗試按名稱獲取屬性或丟棄文檔。

雖然不如根據序號調用屬性效率高,但您可以猜測數據提供者已將XML傳遞給spec。剩下的時間,你可以採取其他行動。

2

答案不,唉。我對你40%的數字感到震驚。我很難相信將「foo」轉換爲ProcessFoo需要很長時間。你確定40%不包括花費的時間執行 ProcessFoo?

是否有可能通過名稱使用此Expat事物訪問屬性?這是更傳統的訪問屬性的方式。我並不是說它會更快,但它可能值得一試。

+2

'Expat thing'是最快速的解析器之一。不要驚訝,你剛剛通過MSFT和IBM銷售XML,並且它沒有擴展:-) – 2009-11-05 17:31:45

+1

Gary,你是對的。我沒有詳細說明ProccessAttribute()函數到底做了什麼,因爲我認爲它與原始問題是無關的......我們在應用程序啓動時解析這些XML文檔,並將元素數據轉儲到sqlite數據庫中供以後處理。 sqlite API允許通過索引綁定參數 - 所以如果我可以確信XML屬性始終與Insert語句中的參數順序相同,那麼事情會更快(更快)。 – 2009-11-05 22:16:59

0

檢查從我記得,Expat是一個非驗證解析器,它更好..所以你可能會取消這個XSD的想法。在很多XML方法中,順序依賴也不是一個好主意(XSD在元素順序方面受到了批評,例如,在MSFT中由XML Web服務的專業或反銷售者)。

做你的自定義編碼,並簡單地擴展你的邏輯更高效的查找或挖掘解析器源。編寫有效替換編碼的工具是很簡單的,同時屏蔽軟件代理和用戶。您希望做到這一點,以便在保持向後兼容性和可逆性的同時輕鬆遷移。此外,去固定大小約束/屬性名稱翻譯。

[考慮你自己的幸運與Expat :)及其原始速度。試想一下,CLR的開發者是多麼愛XML縮放設施,他們經常在的「只是查詢數據庫」過程中的線路發送200MB ..]

6

XML屬性不的訂單,因此沒有以實施。

如果您想要訂購某些東西,則需要XML元素。或者與XML不同的東西。 JSON,YAML和bEncode,例如有兩個映射(它們是無序的)和序列(它們是有序的)。

4

正如其他人指出的,不,你不能依賴屬性排序。

如果我有任何涉及2,500個XML文件和150萬個鍵/值對的進程,我會盡快從XML中獲取這些數據,並將其轉換爲更有用的形式。一個數據庫,一個二進制序列化格式,不管。您沒有從使用XML中獲得任何優勢(除了模式驗證)。每次獲得新的XML文件時,我都會更新我的商店,並從我的流程的主要流程中解析150萬個XML元素。

相關問題