次のようなサンプルコンテンツを含むXmlファイルを作成しました。
<?xml version="1.0" encoding="utf-8" ?>
<Periods>
<PeriodGroup name="HER">
<Period>
<PeriodName>Prehistoric</PeriodName>
<StartDate>-500000</StartDate>
<EndDate>43</EndDate>
</Period>
<Period>
<PeriodName>Iron Age</PeriodName>
<StartDate>-800</StartDate>
<EndDate>43</EndDate>
</Period>
<Period>
<PeriodName>Roman</PeriodName>
<StartDate>43</StartDate>
<EndDate>410</EndDate>
</Period>
</PeriodGroup>
<PeriodGroup name="CAFG">
<Period>
<PeriodName>Prehistoric</PeriodName>
<StartDate>-500000</StartDate>
<EndDate>43</EndDate>
</Period>
<Period>
<PeriodName>Roman</PeriodName>
<StartDate>43</StartDate>
<EndDate>410</EndDate>
</Period>
<Period>
<PeriodName>Anglo-Saxon</PeriodName>
<StartDate>410</StartDate>
<EndDate>800</EndDate>
</Period>
</PeriodGroup>
</Periods>
選択したPeriodGroup内のPeriodノードの子を読み取ることができる必要があります。 PeriodNameは、より理にかなっている場合、Periodの属性である可能性があります。
私はたくさんの例を見てきましたが、どれもまったく正しくないようで、XmlReaderを使用するメソッド、XmlTextReaderを使用するメソッド、使用しないメソッドなどがあります。 Xmlファイルを読むのはこれが初めてなので、誰かがポインタをくれないかと尋ねると思った。何かを試すためだけに機能するものはありますが、不格好に感じます。 VS2010とc#を使用しています。また、多くの人がLINQ-Xmlを使用しているのを見ているので、この方法を使用することの長所と短所を高く評価します。
string PG = "HER";
XmlDocument doc = new XmlDocument();
doc.Load(Server.MapPath("./Xml/XmlFile.xml"));
string text = string.Empty;
XmlNodeList xnl = doc.SelectNodes("/Periods/PeriodGroup");
foreach (XmlNode node in xnl)
{
text = node.Attributes["name"].InnerText;
if (text == PG)
{
XmlNodeList xnl2 = doc.SelectNodes("/Periods/PeriodGroup/Period");
foreach (XmlNode node2 in xnl2)
{
text = text + "<br>" + node2["PeriodName"].InnerText;
text = text + "<br>" + node2["StartDate"].InnerText;
text = text + "<br>" + node2["EndDate"].InnerText;
}
}
Response.Write(text);
}
次のようなXPathアプローチを使用できます。
_XmlNodeList xnl = doc.SelectNodes(string.Format("/Periods/PeriodGroup[@name='{0}']/Period", PG));
_
LINQはXMLよりも読みやすいので好まれます。
これは、指定されたPeriod
PeriodGroup
属性に基づいてname
ノードの子を返します。 HER
:
_XDocument xml = XDocument.Load(HttpContext.Current.Server.MapPath(FileLoc));
var nodes = (from n in xml.Descendants("Periods")
where n.Element("PeriodGroup").Attribute("name").Value == "HER"
select n.Element("PeriodGroup").Descendants().Elements()).ToList();
_
結果:
_<PeriodName>Prehistoric</PeriodName>
<StartDate>-500000</StartDate>
<EndDate>43</EndDate>
<PeriodName>Iron Age</PeriodName>
<StartDate>-800</StartDate>
<EndDate>43</EndDate>
<PeriodName>Roman</PeriodName>
<StartDate>43</StartDate>
<EndDate>410</EndDate>
_
クエリは非常に簡単です
_from n in xml.Descendants("Periods")
_
要素Periods
の子孫要素のコレクションを返します。次に、where
を使用して、属性値に基づいてこのノードのコレクションをフィルタリングします。
_where n.Element("PeriodGroup").Attribute("name").Value == "HER"
_
コレクションをPeriodGroup
の値を持つname
属性を持つHER
要素にフィルターします
最後に、PeriodGroup
要素を選択し、その子孫ノードを取得します
_select n.Element("PeriodGroup").Descendants().Elements()
_
編集(コメントを参照)
この式の結果は単なるクエリであるため、.ToList()
を使用してコレクションを列挙し、必要な値を含むオブジェクトを返します。匿名型を作成して、要素の値を保存することもできます。例:
_var nodes = (from n in xml.Descendants("Period").
Where(r => r.Parent.Attribute("name").Value == "HER")
select new
{
PeriodName = (string)n.Element("PeriodName").Value,
StartDate = (string)n.Element("StartDate").Value,
EndDate = (string)n.Element("EndDate").Value
}).ToList();
//Crude demonstration of how you can reference each specific element in the result
//I would recommend using a stringbuilder here..
foreach (var n in nodes)
{
text += "<br>" + n.PeriodName;
text += "<br>" + n.StartDate;
text += "<br>" + n.EndDate;
}
_
これは、クエリの実行後のnodes
オブジェクトの外観です。
XmlDocument.SelectNodes
メソッドは実際にXPath式を受け入れます。次のように自由に進んでください:
XmlNodeList xnl = doc.SelectNodes("/Periods/PeriodGroup[@name='" + PG + "']/Period");
foreach (XmlNode node in xnl) {
// Every node here is a <Period> child of the relevant <PeriodGroup>.
}
XPathの詳細については、 w3schools をご覧ください。
これを通り抜ける
public static void XMLNodeCheck(XmlNode xmlNode)
{
if (xmlNode.HasChildNodes)
{
foreach (XmlNode node in xmlNode)
{
if (node.HasChildNodes)
{
Console.WriteLine(node.Name);
if (node.Attributes.Count!=0)
{
foreach (XmlAttribute att in node.Attributes)
{
Console.WriteLine("----------" + att.Name + "----------" + att.Value);
}
}
XMLNodeCheck(node);//recursive function
}
else
{
if (!node.Equals(XmlNodeType.Element))
{
Console.WriteLine(node.InnerText);
}
}
}
}
}