1

XMLXML の要素の名前に一致するオブジェクトのプロパティに基づいて、文字列の特定の要素をオブジェクトに処理したいと考えています。

の構造の例XMLは次のとおりです。

<Bar>
  <Body>
    <Header>
      <A>Value</A>
      <B>true</B>
    </Header> 
    <Data>
      <D>Value</D>
    </Data>
    <Data>
      <D>Value2</D>
    <Data>  
  </Body>
</Bar>

XML には多数の要素を含める ことができますが、存在するのは一度だけです。私が設定したクラスは次のとおりです。<Data><Header>

public class Foo
{
  public string A { get; set; }
  public bool B { get; set; }
  public List<FooData> { get; set; }
  public void ProcessXml(string xml)
  {
    XDocument xDoc = XDocument.Load(new StringReader(xml));
    var propVals = (from ele in xDoc.Descendants()
                    join prop in this.GetType().GetProperties() on ele.Name.LocalName equals prop.Name
                    select new
                    {
                      prop = prop,
                      val = new Func<object>(() =>
                        {
                          object objValue = null;
                          prop.PropertyType.TryParse(ele.Value, ref objValue);
                          return objValue;
                        }).Invoke()
                    });
    propVals.ToList().ForEach(x => x.prop.SetValue(this, x.val, null));
  }
}
public class FooData
{
  public string D { get; set; }
}

ProcessXml設定を開始する方法を思いつきましたが、現時点ではHeader値 (A、B)のみを設定しています。同じメソッド内で多くのFooData項目を簡単に追加する方法についてのアイデアはありますか?List

public static class TypeExtensions
{
  public static void TryParse(this Type t, object valIn, ref object valOut)
  {
    //Do some parsing logic
    try{
      out = TypeDescriptor.GetConverter(t).ConvertFromInvariantString(valIn);
      return true;
    } catch(Exception) { return false; }
  }
}
4

2 に答える 2

1

これを 1 行にまとめる簡単な方法がないため、ヘッダーで行ったのと同様の行をたどりました。

var dataElements = (from dataDescendants in (from ele2 in xDoc.Descendants()
                                             Where ele2.Name.LocalName == "Data"
                                             select ele2.Descendants())
                    from dataDescendant in dataDescendants
                    join prop in typeof(FooItem).GetProperties() on prop.Name equals dataDescendant.Name.LocalName
                    select Element = dataDescendant, Property = prop, dataDescendants
                    group by dataDescendants into g = group
                    select g).ToList();
dataElements.ForEach(dataElement =>
                     {
                       FooItem fi = new FooItem();
                       dataElement.ToList.ForEach(x =>
                                                  {
                                                    object objVal = null;
                                                    x.Property.PropertyType.TryParse(x.Element.Value, objVal);
                                                    x.Property.SetValue(fi, objVal, null);
                                                  }
                       DataItems.Add(fi);
                     }
于 2013-01-31T11:29:11.303 に答える
0

XMLが本当に単純な場合は、シリアル化を使用して、モデルクラスを適切なXMLシリアル化属性で装飾することにより、この動的/自己読み込み動作を取得できますが、ドキュメントのインデントのレベルごとに少なくとも1つのクラスが必要です。

void Main()
{
    var xml = @"<Bar>
  <Body>
    <Header>
      <A>Value</A>
      <B>true</B>
    </Header> 
    <Data>
      <D>Value</D>
    </Data>
    <Data>
      <D>Value2</D>
    </Data>  
  </Body>
 </Bar>";

    var serializer = new XmlSerializer(typeof(Bar));
    serializer.Deserialize( new MemoryStream( Encoding.ASCII.GetBytes( xml ) ) ).Dump();
}

public class Bar
{
    public Body Body { get; set; }
}

public class Body
{
    public Header Header { get; set; }

    [XmlElement]
    public Data[] Data { get; set; }
}

public class Header
{
    public string A { get; set; }
    public string B { get; set; }
}

public class Data
{
    public string D { get; set; }
}

編集:ヘッダー要素が1つしかないことを見逃しました)

于 2013-01-30T15:05:26.467 に答える