0

XDocumentを使用してインスタンスからデータを解析しLinq to XML、に保存しようとしていIEnumerable<MyClass>ます。xmlドキュメントからすべての要素を取得したくないのでElementAt(#index)、値を取得するために使用しています。ただし、必要な要素がドキュメントにない場合は、インデックスが範囲外の例外になります。このドキュメントから値を解析するためのより良い方法はありますか?コードは次のとおりです。

XMLドキュメントは次のようになります。

<someotherelement>   /* I dont want the "someotherelement" part either */
   <subelement></subelement>
   <subelement></subelement>
</someotherelement>
<result>
   <doc>
      <int name="personid">8394</int> /* I don't want this value so I am skipping it */
      <str name="name">James</str>
      <str name="address">30 Awesome Lane</str>
      <arr name="randomearray"> /* I want to skip this too */
         <str name="random1">SomeValue</str>
         <str name="random2">SomeValue</str>
         <str name="random2">SomeValue</str>
      </arr>
      <str name="city">Awesome City</str>
      <str name="state">CA</str>
      <int name="zipcode">84392</int>
      <str name="country">USA</str>
      <str name="phonenumber">8309933820</str>
      <date name="reportdate">2012-07-27T06:01:05.256Z</date>
   </doc>

   /* This is missing address and country */
   <doc>
      <int name="personid">10394</int> /* I don't want this value so I am skipping it */
      <str name="name">Mathew</str>
      <arr name="randomearray"> /* I want to skip this too */
         <str name="random1">SomeValue</str>
         <str name="random2">SomeValue</str>
         <str name="random2">SomeValue</str>
      </arr>
      <str name="city">Not Awesome City</str>
      <str name="state">CA</str>
      <str name="zipcode">58439</str>
      <str name="phonenumber">8309933820</str>
      <date name="reportdate">2012-07-27T06:01:05.256Z</date>
   </doc>
</result>    

クラス:

public class Doc
{
    public string Name {get;set;}
    public string Address{get;set;}
    public string City {get;set;}
    public string State {get;set;}
    public int ZipCode {get;set;}
    public string Country {get;set;}        
    public string PhoneNumber {get;set;}
    public DateTime ReportDate {get;set;}
}

Linq To Xml

string pathToXml = "http://www.foo.com/something";
var doc = XDocument.Load(pathToXml);
IEnumerable<Doc> myDoc = from item in doc.Descendants("doc")
                 select new Doc
                 {
                   Name = item.Element("str").Value,
                   Address = item.Element("str").ElementsAfterSelf("str").First().Value,
                   City = item.Element("str").ElementsAfterSelf("str").ElementAt(1).Value,
                   State = item.Element("str").ElementsAfterSelf("str").ElementAt(2).Value,
                   ZipCode = Convert.ToInt32(item.Element("int").Value)
                   Country = item.Element("str").ElementsAfterSelf("str").ElementAt(3).Value,
                   PhoneNumber = item.Element("str").ElementsAfterSelf("str").ElementAt(4).Value,
                   ReportDate = Convert.ToDateTime(item.Element("date").Value)
                 };
4

2 に答える 2

2

たとえば、属性の値を使用して、要素をより快適に指定できるXPathを使用することができます。これは、あなたの場合に役立ちます。

ステートメントの繰り返しを避けるために、拡張メソッドと組み合わせると、次のようになります。

public static string GetElementValue(this XElement element, string query)
{
    var elem = element.XPathSelectElement(query);
    return elem == null ? null : elem.Value;
}

例:

select new Doc
{
    Name = item.GetElementValue("str[@name='name']"),
    ...
}
于 2012-08-09T21:37:44.037 に答える
1

拡張メソッドを追加してこれを修正しました:

public static class Extensions {
  public static string GetValue(this XElement element) {
    return element == null ? null : element.Value;
  }
}

そしてAttribute()、値のベース選択を使用します。

IEnumerable<Doc> myDoc = from item in doc.Descendants("doc")
                 select new Doc
                 {
                   Name = item.Element("str").Value,
                   Address = item.Element("str").ElementsAfterSelf("str").First().Value,
                   City = item.Element("str").ElementsAfterSelf("str").Where(el => (string)el.Attribute("name") == "city").FirstOrDefault().GetValue(),
                   State = item.Element("str").ElementsAfterSelf("str").Where(el => (string)el.Attribute("name") == "state").FirstOrDefault().GetValue(),
                   ZipCode = Convert.ToInt32(item.Element("int").Value),
                   Country = item.Element("str").ElementsAfterSelf("str").Where(el => (string)el.Attribute("name") == "country").FirstOrDefault().GetValue(),
                   PhoneNumber = item.Element("str").ElementsAfterSelf("str").Where(el => (string)el.Attribute("name") == "phonenumber").FirstOrDefault().GetValue(),
                   ReportDate = Convert.ToDateTime(item.Element("date").Value)
                 };

その拡張メソッドには組み込みがあるかもしれませんが、私が知っているものはありません。

于 2012-08-09T21:37:17.780 に答える