2012-11-16 34 views
0

我有一个类可以创建各种不同的XML方案。我使用条件运算符为可选元素和属性通过一个(非常长)语句创建各种动态XDocument。解析XDocument的友好方法

我现在需要将XDocuments转换回类,但是因为它们来自不同的方案,所以许多元素和子元素可能是可选的。我知道这样做的唯一方法是使用很多if语句。

这种方法似乎不是很LINQ,并且比创建XDocument时使用了更多的代码,所以我想知道是否有更好的方法来做到这一点?

一个例子是得到

<?xml version="1.0"?> 
<root xmlns="somenamespace"> 
    <object attribute1="This is Optional" attribute2="This is required"> 
     <element1>Required</element1> 
     <element1>Optional</element1> 
     <List1> 
      Optional List Of Elements 
     </List1> 
     <List2> 
      Required List Of Elements 
     </List2> 
    </object> 
</root> 

进入

public class Object() 
{ 
    public string Attribute1; 
    public string Attribute2; 
    public string Element1; 
    public string Element2; 
    public List<ListItem1> List1; 
    public List<ListItem2> List2; 
} 

在更LINQ友好的方式莫过于:

public bool ParseXDocument(string xml) 
{ 
    XNamespace xn = "somenamespace";    
    XDocument document = XDocument.Parse(xml); 

    XElement elementRoot = description.Element(xn + "root"); 
    if (elementRoot != null) 
    { 
     //Get Object Element 
     XElement elementObject = elementRoot.Element(xn + "object"); 
     if(elementObject != null) 
     { 
      if(elementObject.Attribute(xn + "attribute1") != null) 
      { 
       Attribute1 = elementObject.Attribute(xn + "attribute1"); 
      } 
      if(elementObject.Attribute(xn + "attribute2") != null) 
      { 
       Attribute2 = elementObject.Attribute(xn + "attribute2"); 
      } 
      else 
      { 
       //This is a required Attribute so return false 
       return false; 
      } 
      //If, If/Elses get deeper and deeper for the next elements and lists etc.... 
     } 
     else 
     { 
      //Object is a required element so return false 
      return false; 
     } 
    } 
    else 
    { 
     //Root is a required element so return false 
     return false; 
    } 
    return true; 
} 

更新:我只想澄清ParseXDocument方法在“Object”类中。每次接收到xml文档时,Object类实例都会更新其中一些或全部值。

回答

1

代码:

private static readonly XNamespace xn = "somenamespace"; 

public bool ParseXDocument(string xml) 
{ 
    XDocument document = XDocument.Parse(xml); 

    var obj = document.Root.Element(xn + "object"); 
    if (obj == null) 
     return false; 

    Attribute1 = (string)obj.Attribute("attribute1"); 
    Attribute2 = (string)obj.Attribute("attribute2"); 
    Element1 = (string)obj.Element(xn + "element1"); 
    Element2 = (string)obj.Elements(xn + "element1").ElementAtOrDefault(1); 
    // ... 

    return Validate(); 
} 
+0

谢谢DTB-抱歉应该让自己更清楚。我没有创建一个新类,我正在更新现有类中的值。通过定期发送新值,并且每个xml文档都会更新一些值到所有值。 ParseXDocument方法将在“Object”类中。 – Oli

0

下面我有一对夫妇的扩展方法可以使用,可以帮助达到你想要的可读性。当前表单中的代码不支持返回true/false,取决于是否找到了所有必需的元素。我建议在这方面采用dtb的建议,只解析出细节,然后对其进行验证。

有一些缺点,例如对XML结构的重复迭代,但有一点想象力,我相信如果它成为一个问题,你可以克服。

以下是MyObject的样子: public class MyObject { public string Attribute1; public string Attribute2; public string Element1; 公共字符串Element2; public List List1; public List List2;

public void ParseXDocument(string xml) 
    { 
     XNamespace xn = "somenamespace";    
     XDocument document = XDocument.Parse(xml); 

     XElement elementRoot = document.Root; 
     elementRoot.MatchElement(xn.GetName("object"), xObject => { 
      xObject.MatchAttribute("attribute1", (x,a) => this.Attribute1 = (string)a); 
      xObject.MatchAttribute("attribute2", (x,a) => this.Attribute2 = (string)a); 
      xObject.MatchElement(xn.GetName("element1"), x => this.Element1 = (string)x); 
      xObject.MatchElement(xn.GetName("element2"), x => this.Element2 = (string)x); 
     }); 
    } 
} 

下面是支持它的扩展方法: 公共静态类XElementExtensions {

public static XElement MatchAttribute(this XElement x, XName name, Action<XElement, XAttribute> action) { 
     foreach (var a in x.Attributes(name)) { 
      action(x, a); 
     } 

     return x; 
    } 

    public static XElement MatchElement(this XElement x, XName name, Action<XElement> action) { 
     foreach (var child in x.Elements(name)) { 
      action(child); 
     } 

     return x; 
    } 
} 

最后,这里是我的LinqPad用来测试出来一些样本驱动程序代码:

void Main() 
{ 
    var xml = @"<?xml version=""1.0""?> 
<root xmlns=""somenamespace""> 
    <object attribute1=""This is Optional"" attribute2=""This is required""> 
     <element1>Required</element1> 
     <element2>Optional</element2> 
     <List1> 
      Optional List Of Elements 
     </List1> 
     <List2> 
      Required List Of Elements 
     </List2> 
    </object> 
</root> 
    "; 

    var o = new MyObject(); 

    o.ParseXDocument(xml); 
    o.Dump(); 
}