そのサンプルXMLでの属性の使用に問題はありません。属性には、要素にはないいくつかの制限と、いくつかの重要な利点があります。
まず、制限事項:
- 属性には単純なコンテンツのみを含めることができます。
- 属性名は、要素内で一意である必要があります。
- 定義上、属性の順序はXMLでは重要ではありません。DOMに依存して、特定の順序で属性を反復処理または保存することはできません。
node() | @*
属性はノードではありません。つまり、XPath( XSLT ID変換で使用されるパターンなど)およびDOM(.NETなど)で属性にアクセスする方法には、属性がない場合でもXmlAttribute
派生するいくつかの偏心があります。XmlNode
ノードであり、オブジェクトのリストであっても派生XmlAttributeCollection
しません。これには十分な理由がありますが、初めて使用する場合はかなり混乱します)。XmlNodeList
XmlNode
重要な利点:
- 属性名は要素内で一意である必要があり、単純なコンテンツのみを含めることができるため、属性値を設定および取得するDOMメソッドは、要素内で値を設定および取得するDOMメソッドよりもはるかに簡単に使用できます。
- 属性の順序は重要ではないため、属性を作成して使用するコードが属性の順序に関係する必要はありません。
- 属性には単純なコンテンツしか含まれない可能性があるため、属性のスキーマ定義を作成する方が簡単です。
- 属性のマークアップは、要素のマークアップよりも簡潔です。
属性はマップ/辞書に非常にきれいに同形化します。名前を有効なXML名に制限し、値をテキストに制限しても問題がない限り、名前と値のペアで構成されるデータ構造の永続的な形式として属性を使用できます。データ構造を構築する場合は、属性を使用できます。入力する順序は関係ありません。
(これは大きな問題を引き起こす可能性があります。WPFでは、XAMLの属性を使用して、設定時に副作用のあるオブジェクトプロパティの値を格納できます。これを行うと、設定Binding
したからといって、診断が非常に困難なバグが発生します。設定する前のXAMLは、XAMLが表すオブジェクトを構築するときにXAMLが実行SelectedItem
することを意味するわけではなく、まだ設定されていないオブジェクトXamlReader
に設定しようとすると、例外がスローされます。 XAMLを一日中見ることができ、なぜそれが起こっているのかわかりません。)SelectedItem
Binding
コードでは、属性を使用する利点は自明です。DOM(C#)foo
を使用して要素の属性の値を設定および取得するには:XmlDocument
elm.SetAttribute("foo", value);
value = elm.GetAttribute("foo");
foo
要素の要素の値を設定および取得するには、次のようにします。
XmlElement fooElm = (XmlElement)elm.SelectSingleNode("foo");
if (fooElm == null)
{
elm.OwnerDocument.CreateElement("foo");
elm.AppendChild(fooElm);
}
fooElm.InnerText = value;
XmlElement fooElm = (XmlElement)elm.SelectSingleNode("foo");
value = fooElm != null ?? fooElm.InnerText : "";
上記を行うには確かにより効率的な方法があります(ヘルパーメソッドを作成する、XDocument
代わりに使用するXmlDocument
、またはDOMを完全に回避してシリアル化を使用する)が、要素を操作するのは本質的に複雑です。
あなたの例では、属性を使用してもおそらく問題ありません。順序が重要でない単純な名前/値ペアのマッピングを表しているように見えます。例外はタイトルかもしれません。それらにマークアップを含めることが望ましい場合は、悲しみに陥ります。
編集:
実際、XamlReader
はXAMLに表示される順序で属性を処理すると思います。したがって、XAMLでBinding
以前に設定した場合、XAMLの実際のテキストから読み取ってSelectedItem
いる限り、例外は発生しない可能性があります。XamlReader
リスクは、XMLドキュメントを読み書きするツールが、XAMLドキュメントの属性の順序を変更することです。KaXamlは、編集するXAMLドキュメントの属性の順序を保持しますか?する必要はありません。
とにかく、XAMLのソリューションは単純です:これを行う代わりに:
<ListBox Binding="{...}" SelectedItem="..." ... />
これを行う:
<ListBox>
<ListBox.Binding>...</ListBox.Binding>
<ListBox.SelectedItem>...</ListBox.SelectedItem>
...