最初の
.NETブログ投稿「
Working with XML 」で、人々はLINQ to XMLについてコメントでコメントしました。 さて、Microsoftのこの新しいテクノロジの動作原理を明らかにしてみましょう。
オーディオ録音のカタログを維持するためのベースを作成しましょう。
ベースはトラックで構成されます:
データベースからさまざまな選択を追加、編集、削除、および選択する方法を学習します。
最初に、コンソールアプリケーションを作成し(プロジェクトをC#で記述しますが、本質はだれにとっても明らかです)、必要な名前空間を接続します
System.Xml.Linqを使用します。
XMLファイルの作成
LINQを使用して、いくつかのテストレコードを含むデータベースのXMLファイルを作成しましょう。
//作業XMLファイルへのパスを設定します
string fileName = "base.xml";
//コンポジション番号のカウンター
int trackId = 1;
//ネストされたコンストラクターによる作成。
XDocument doc = new XDocument(
新しいXElement(「ライブラリ」、
新しいXElement(「トラック」、
新しいXAttribute(「id」、trackId ++)、
新しいXAttribute(「ジャンル」、「ラップ」)、
新しいXAttribute( "time"、 "3:24")、
new XElement( "name"、 "Who We Be RMX(feat。2Pac)")、
新しいXElement(「アーティスト」、「DMX」)、
new XElement( "アルバム"、 "The Dogz Mixtape:Who's Next?!"))、
新しいXElement(「トラック」、
新しいXAttribute(「id」、trackId ++)、
新しいXAttribute(「ジャンル」、「ラップ」)、
新しいXAttribute( "time"、 "5:06")、
new XElement( "name"、 "Angel(ft。Regina Bell)")、
新しいXElement(「アーティスト」、「DMX」)、
新しいXElement(「アルバム」、「...そしてその後Xがありました」))、
新しいXElement(「トラック」、
新しいXAttribute(「id」、trackId ++)、
新しいXAttribute(「ジャンル」、「ブレイクビート」)、
新しいXAttribute( "time"、 "6:16")、
新しいXElement( "name"、 "Dreaming Your Dreams")、
新しいXElement(「アーティスト」、「ハイブリッド」)、
新しいXElement(「アルバム」、「広角」))、
新しいXElement(「トラック」、
新しいXAttribute(「id」、trackId ++)、
新しいXAttribute(「ジャンル」、「ブレイクビート」)、
新しいXAttribute(「時間」、「9:38」)、
新しいXElement( "name"、 "Finished Symphony")、
新しいXElement(「アーティスト」、「ハイブリッド」)、
新しいXElement(「アルバム」、「広角」))));
//ドキュメントを保存します
doc.Save(fileName);
これで、プログラムの起動後、フォルダーに次のコンテンツのXMLファイルが表示されます。
<?xml version = "1.0" encoding = "utf-8"?>
<ライブラリ>
<トラックID = "1"ジャンル= "ラップ"時間= "3:24">
<name> Who We Be RMX(feat。2Pac)</ name>
<artist> DMX </ artist>
<アルバム> The Dogz Mixtape:Who's Next?!</ album>
</ track>
<トラックID = "2"ジャンル= "ラップ"時間= "5:06">
<name>エンジェル(ft。Regina Bell)</ name>
<artist> DMX </ artist>
<album> ...そしてXがありました</ album>
</ track>
<トラックID = "3"ジャンル= "ブレイクビート"時間= "6:16">
<name> Dreaming Your Dreams </ name>
<artist>ハイブリッド</ artist>
<アルバム>広角</アルバム>
</ track>
<track id = "4"ジャンル= "Break Beat" time = "9:38">
<name>シンフォニーの終了</ name>
<artist>ハイブリッド</ artist>
<アルバム>広角</アルバム>
</ track>
</ library>
XmlDocumentコードを使用して同様のファイルを作成するには、約2倍かかりました。 上記のコードでは、XDocumentクラスのコンストラクターを使用しました。これは、ドキュメントを初期化するときに使用する子要素のリストをパラメーターとして受け取ります。 使用されるXElementコンストラクターは、パラメーターとして、作成する要素の名前と初期化要素のリストを受け取ります。 便利なことに、これらの要素に新しいXElementとXAttributeの両方を指定できます。 後者は、独自の属性としてファイルにレンダリングされます。 このようなデザイナーのネストを使用するのが嫌で、そのようなコードが面倒な場合は、従来のバージョンに書き換えることができます。 以下のコードは同じXMLファイルを出力します:
XDocument doc = new XDocument();
XElement library = new XElement( "library");
doc.Add(ライブラリ);
// track要素を作成します
XElement track = new XElement( "track");
//必要な属性を追加します
track.Add(新しいXAttribute( "id"、1));
track.Add(新しいXAttribute( "genre"、 "Rap"));
track.Add(新しいXAttribute( "time"、 "3:24"));
//要素「name」を作成します
XElement name = new XElement( "name");
name.Value = "Who We Be RMX(feat。2Pac)";
track.Add(名前);
//要素「アーティスト」を作成します
XElementアーティスト=新しいXElement(「アーティスト」);
artist.Value = "DMX";
track.Add(アーティスト);
//変更のために、「アルバム」要素を解析しましょう
string albumData = "<album> The Dogz Mixtape:Who's Next?!</ album>";
XElement album = XElement.Parse(albumData);
track.Add(アルバム);
doc.Root.Add(トラック);
/ *
*類推により他の要素を追加する
* /
//ドキュメントを保存します
doc.Save(fileName);
当然、状況に応じて必要な方法を選択する必要があります。
ファイルからデータを読み取る
次に、既に受信したファイルからデータを読み取って、コンソールで認識できる便利な形式で表示してみましょう。
//作業XMLファイルへのパスを設定します
string fileName = "base.xml";
//ファイルからデータを読み取ります
XDocument doc = XDocument.Load(fileName);
//ライブラリの各要素を調べます
//(この要素はdoc.Rootプロパティからすぐにアクセスできます)
foreach(doc.Root.Elements()のXElement el)
{
//要素名とid属性値を出力します
Console.WriteLine( "{0} {1}"、el.Name、el.Attribute( "id")。Value);
Console.WriteLine( "属性:");
//ループ内のすべての属性を表示し、同時にそれらがどのように文字列に変換されるかを確認します
foreach(el.Attributes()のXAttribute attr)
Console.WriteLine( "{0}"、attr);
Console.WriteLine( "Elements:");
//すべての子要素の名前とその値をループに出力します
foreach(el.Elements()のXElement要素)
Console.WriteLine( "{0}:{1}"、element.Name、element.Value);
}
ここで、コードには、複雑なものはなく、コメントが記載されていると思います。 コンソールでプログラムを開始すると、次の結果が表示されます。
トラック1
属性:
id = "1"
ジャンル= "ラップ"
時間= "3:24"
要素:
名前:Who We Be RMX(feat。2Pac)
アーティスト:DMX
アルバム:The Dogz Mixtape:Who's Next?!
トラック2
属性:
id = "2"
ジャンル= "ラップ"
時間= "5:06"
要素:
名前:エンジェル(ft。Regina Bell)
アーティスト:DMX
アルバム:...そして、Xがあった
トラック3
属性:
id = "3"
ジャンル=「ブレイクビート」
時間= "6:16"
要素:
名前:Dreaming Your Dreams
アーティスト:ハイブリッド
アルバム:広角
トラック4
属性:
id = "4"
ジャンル=「ブレイクビート」
時間= "9:38"
要素:
名前:完成した交響曲
アーティスト:ハイブリッド
アルバム:広角
データ変更
すべてのライブラリノードを調べて、track要素のId属性を1増やしてみましょう。
(ファイルへのパスの宣言とコンソールへの出力結果を引用しないので、不必要な情報で記事をオーバーロードしないように、すべてをコンパイルし、すべてが機能します:)) :
//ライブラリから最初の子ノードを取得します
XNodeノード= doc.Root.FirstNode;
while(node!= null)
{
//現在のノードが要素であることを確認します
if(node.NodeType == System.Xml.XmlNodeType.Element)
{
XElement el =(XElement)ノード;
// id属性値を取得してInt32に変換します
int id = Int32.Parse(el.Attribute( "id")。Value);
//カウンタを1つ増やし、値を割り当てます
id ++;
el.Attribute( "id")。Value = id.ToString();
}
//次のノードに移動します
node = node.NextNode;
}
doc.Save(fileName);
それでは、タスクに対してより正確な方法でこれを実行してみましょう。
foreach(doc.Root.ElementsのXElement el( "track"))
{
int id = Int32.Parse(el.Attribute( "id")。Value);
el.SetAttributeValue( "id"、--id);
}
doc.Save(fileName);
ご覧のとおり、この方法はより適しています。
新しいエントリを追加する
ライブラリに新しいトラックを追加すると同時に、LINQを使用してトラックの次の一意のIDを計算します。
int maxId = doc.Root.Elements( "track")。Max(t => Int32.Parse(t.Attribute( "id")。Value));
XElement track = new XElement( "track"、
新しいXAttribute(「id」、++ maxId)、
新しいXAttribute(「ジャンル」、「ブレイクビート」)、
新しいXAttribute( "time"、 "5:35")、
新しいXElement(「name」、「Higher Than A Skyscraper」)、
新しいXElement(「アーティスト」、「ハイブリッド」)、
new XElement( "album"、 "Morning Sci-Fi"));
doc.Root.Add(トラック);
doc.Save(fileName);
これは、トラックのid属性の最大値を計算するためにすべての要素へのリクエストが発生する方法です。 追加すると、結果の最大値が増加します。 要素の追加は、Addメソッドの呼び出しに限定されます。 ルートに要素を追加することに注意してください。そうしないと、2つのルート要素を宣言してXMLドキュメントの構造に違反します。 また、ドキュメントをディスクに保存することを忘れないでください。保存する瞬間まで、XDocumentの変更はXMLファイルに反映されません。
アイテムを削除する
DMXアーティストのすべての要素を削除してみましょう。
IEnumerable <XElement> tracks = doc.Root.Descendants( "track")。どこ(
t => t.Element( "artist")。Value == "DMX")。ToList();
foreach(トラック内のXElement t)
t.Remove();
この例では、最初にartstの子が基準を満たすすべてのトラックを選択してから、これらの要素をループで削除しました。 ToList()選択の最後の呼び出しは重要です。 したがって、削除するすべての要素を個別のメモリ位置に修正します。 ループで直接実行するレコードセットから削除することにした場合、最初の要素と後続のNullReferenceExceptionが削除されます。 そのため、これを念頭に置くことが重要です。
xaoccpsのアドバイスにより、より簡単な方法で削除できます。 IEnumerable <XElement> tracks = doc.Root.Descendants( "track")。どこ(
t => t.Element( "artist")。Value == "DMX");
tracks.Remove();
この場合、ToList()関数を呼び出して取得した結果をリストする必要はありません。 なぜこのメソッドが元々
コメントで説明されているように使用されないのか:)
トラックデータベースへの追加クエリ
トラックを期間ごとに逆順で並べ替えます。
IEnumerable <XElement> tracks = doc.Root.Elementsのtから(「track」)
let time = DateTime.Parse(t.Attribute( "time")。Value)
降順
tを選択します。
foreach(トラック内のXElement t)
Console.WriteLine( "{0}-{1}"、t.Attribute( "time")。Value、t.Element( "name")。Value);
ジャンル、アーティスト、アルバム名、トラック名でアイテムを並べ替えます:
IEnumerable <XElement> tracks = doc.Root.Elementsのtから(「track」)
orderby t.Attribute( "genre")。値、
t.Element( "アーティスト")。値、
t.Element(「アルバム」)値、
t.Element( "name")。値
tを選択します。
foreach(トラック内のXElement t)
{
Console.WriteLine( "{0}-{1}-{2}-{3}"、t.Attribute( "genre")。値、
t.Element( "アーティスト")。値、
t.Element(「アルバム」)値、
t.Element( "name")。Value);
}
各アルバムのトラック数を表示する簡単なクエリ:
var albumGroups = doc.Root.Elements( "track")。GroupBy(t => t.Element( "album")。Value);
foreach(albumGroupsのIGrouping <string、XElement> a)
Console.WriteLine( "{0}-{1}"、a.Key、a.Count());
結論
下位レベルでXMLを操作するためにSystem.Xml名前空間を習得した後、System.Xml.Linqの使用に自由に切り替えてください。悪魔は描かれているほど怖くないので、書かれた記事がこれをより速くするのに役立つことを願っています。 上記の例からわかるように、多くのことがより簡単になり、コードの行数が削減されます。 これにより、開発速度から始めて、以前に記述したコードのメンテナンスが簡単になるという明らかな利点が得られます。