スキーマを使用して XML 属性の順序を強制できますか?
-
18-09-2019 - |
質問
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>
完全なアプリケーション構成は、約 2,500 個のこれらの XML ファイルで構成されます (これは、150 万を超えるキーと値の属性ペアに変換されます)。XML ファイルはさまざまなソース/チームから提供され、スキーマに対して検証されます。ただし、場合によっては、 <value/>
ノードは次のようになります。
<value name="bar1" id="BAR1" description="the bar" size="20" ... />
またはこれ:
<value id="BAT1" description="the bat" name="bat1" size="25" ... />
このプロセスを高速化するために、次のものを使用しています 駐在員 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()
「キー」を読み取り、その値をどう扱うかを決定する関数。 アプリをプロファイリングすると、合計 XML 解析時間の約 40% が名前/文字列によるこれらの属性の処理に費やされていることがわかりました。
属性の順序を保証/強制できれば、プロセス全体が大幅に高速化される可能性があります (まず、文字列比較を行わないでください)。 ProcessAttribute()
)。たとえば、「id」属性が いつも 1 番目の属性は直接処理できます。
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 ドキュメントで属性の順序を強制する方法はありますか?答えが「ノー」の場合、実行時のパフォーマンスに大きな影響を与えない代替案を誰か提案していただけないでしょうか?
解決
他のヒント
XML属性ないのHAVE のため、したがって、強制するいかなる順序はありません。
あなたが注文した何かをしたい場合は、は、XML要素を必要としています。またはXMLから別の何か。 JSON、YAMLとbEncode、例えば(順不同です)マップと(注文されている)配列の両方を持っています。
、いいえ、あなたは属性の順序に依存することはできません。
私は全く2,500のXMLファイルと150万のキー/値のペアを含む任意のプロセスを持っていた場合、私はできるだけ早く私はおそらくできる限りXMLの外に、より使用可能な形式にそのデータを得るでしょう。データベース、バイナリシリアル化形式、どの。あなたは(スキーマ検証以外の)XMLを使用してのうち、いずれかの利点を取得していません。私は私の店私は新しいXMLファイルを持ってたびに更新し、私のプロセスの主要な流れのうち、150万個のXML要素を解析取ると思います。
答え は いや、残念ながら。40%という数字には驚きました。「foo」を ProcessFoo に変換するのにそれほど時間がかかるとは信じられません。40% には、次の作業にかかる時間は含まれていませんか? 実行する プロセスフー?
この Expat を使用して名前で属性にアクセスすることは可能ですか?これは、属性にアクセスするためのより伝統的な方法です。速くなるとは言いませんが、試してみる価値はあるかもしれません。
私は、XMLスキーマことをサポートしていないと思います彼らは、特定の名前と一致する必要があります - 私はあなたがXSDでこれらの属性のための順序を定義することができますどのように表示されていない
。私は特定の順序で来XMLノードに必ず属性を作るために他の方法を知らない - わからない場合のSchematronなど他のXMLスキーマのメカニズムのいずれかNGがそれをサポートするリラックス....
私は、XML文書内の属性の順序を強制する方法はありません確信しています。私は、ビジネス・プロセスや、契約書やその他の書類など、他の人的要因を介してそれを主張できると仮定するつもりです。
あなたがちょうど最初の属性は、「ID」だった、と確かに名前をテストしたと仮定した場合? yesの場合は、値を使用しない場合、あなたは名前で属性を取得したり、文書を捨てることを試みることができます。
のように効率的ではないが、その順序で属性を呼び出すと、時代のいくつかの非ゼロの数は、あなたのデータプロバイダは、仕様にXMLを配信していることを推測することができますしながら。残りの時間は、あなたが他のアクションを取ることができます。
単なる推測ですが、追加してみてはいかがでしょうか 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 は順序を強制しません。しかし、それはパーサーがだまされて速く動作することができないという意味ではないので、実際に動作する場合に備えて上記の回答を公開しておきます。
私が思い出したものから、Expatのは...非検証パーサーとそれのために優れているので、おそらくそのXSDのアイデアをスクラップすることができます。どちらも多くのXMLのアプローチで順序に依存良いアイデア(XSDは、MSFTでXML Webサービスのプロまたは抗売り手によって、例えば、要素の順序に戻って一日でたくさんの一体を批判しました)がありません。
カスタムエンコーディングを行うと、単により効率的な検索のためにどちらかあなたのロジックを拡張したり、パーサーソースに掘ります。あなたが、下位互換性と可逆性を維持しながら、それが簡単に移行されるので、これを行うたい...それから、ソフトウェアエージェントとユーザーを遮断しながら、効率的な交換をコードする周りの工具を書くことは簡単です。また、固定サイズの制約/属性名翻訳のために行く。
[Expatの:)とその生のスピードで自分は幸運を検討してください。彼らは日常ただデータベースを照会 "の過程でワイヤーに200メガバイトを送り、CLRの開発者は、XMLスケーリング施設を愛する方法を想像してみて..]