2011-10-24 51 views
1

我想將XML層次結構讀入內存中的對象樹。 XML樹可以有n層兒童。我不知道確切的數字。我的內存中的對象具有綁定到樹控件的子級和父級屬性。在不知道結構的情況下以通用方式讀取xml文件/字符串

當我不知道如何正確調用/寫入xml元素標記時,如何以通用方式將xml文件/字符串讀入我的內存中對象?

例如有人可以爲我提供一個xml結構的單元,其中每個單元有很多單元等等......所以我知道xml標籤是「單元」,但它也可能是「模塊」或其他任何東西......它必須工作通用,但我不會要求用戶輸入XML元素標籤名稱,如「單位」。

這是可能的,我想達到什麼目的?

+1

您似乎在描述DOM的概念。您的帶有子節點和父屬性的通用內存對象聽起來完全像DOM節點。 –

+0

我的內存中的對象是作爲treeview控件的數據源的ViewModels – msfanboy

回答

1

無論哪種方式,你必須知道該節點名稱解析層次至少你必須有一個定義。恕我直言,XElement是唯一一種通用的XML解析器。例如,你有這樣的XML:

<module name="core"> 
    <modules> 
     <module name="xml"> 
      <modules> 
       <module name="reader" /> 
       <module name="writer" /> 
      </modules> 
     </module> 
     <module name="json"> 
      <modules> 
       <module name="serializer" /> 
       <module name="deserializer" /> 
      </modules> 
     </module> 
    </modules> 
</module> 

正如我剛纔所說,你應該有像root node一些定義必須分層元素名稱和孩子容器必須root node name + s。這是一種簡單的方法,您可以允許您的用戶指定他們希望的任何節點名稱,但有一些限制。

您可以解析XML使用XElement這樣的:

XElement xElement = XElement.Load(@"path\to\your\xml\file"); 
string rootNodeName = xElement.Name.LocalName; 
IEnumerable<XElement> xElements = xElement.Descendants(rootNodeName + "s"); 

當然,你可以LinqxElements和解析可以重現建立你的樹控制的層次結構。

您可以採取的XElement踢開始與下面這些鏈接:

希望這有助於。

+1

我知道.descendants和它看起來你的代碼將工作;-)我會按照你的建議:rootNodeName +「s」);多數民衆贊成我認爲我現在! – msfanboy

1

我只是將它加載到XmlDocument,然後構建樹通過XmlNodes

+0

@Jakuk如果我不知道客戶xml文件及其結構,那麼讀取每個節點並假定我做的所有事情都是正確的,那將是瘋狂的......首先,從哪裏可以知道xml元素標籤名稱? – msfanboy

+1

@msfanboy - 要麼你知道節點名稱,只想讀取它們,或者你不知道它們,並且想要讀取整個文件。沒有別的辦法。你問'當節點不知道時如何以通用的方式讀取xml文件。如果你想要一個不同的答案,請問另一個問題 –

0

喜歡這個?

using System.Xml ; 
using System.IO; 
class Program 
{ 
    static void Main(string[] args) 
    { 
    using (Stream inputStream = OpenXmlStream()) 
    { 
     XmlDocument document = new XmlDocument() ; 
     document.Load(inputStream) ; 
     Process(document) ; 
    } 
    } 
    static Stream OpenXmlStream() 
    { 
    // provide an input stream for the program 
    } 
    static void Process(XmlDocument document) 
    { 
    // do something useful here 
    } 
} 
1

我相信有可能實現你想達到的目標。我會做這樣的事情:

class GenericNode 
{ 
    private List<GenericNode> _Nodes = new List<GenericNode>(); 
    private List<GenericKeyValue> _Attributes = new List<GenericKeyValue>(); 
    public GenericNode(XElement Element) 
    { 
    this.Name = Element.Name; 
    this._Nodes.AddRange(Element.Elements() 
           .Select(e => New GenericNode(e)); 
    this._Attributes.AddRange(
       Element.Attributes() 
         .Select(a => New GenericKeyValue(a.Key, a.Value)) 
    } 

    public string Name { get; private set; } 
    public IEnumerable<GenericNode> Nodes 
    { 
    get 
    { 
     return this._Nodes; 
    }  
    } 
    public IEnumerable<GenericKeyValue> Attributes 
    { 
    get 
    { 
     return this._Attributes; 
    } 
    } 
} 

class GenericKeyValue 
{ 
    public GenericKeyValue(string Key, string Value) 
    { 
    this.Key = Key; 
    this.Value = Value; 
    } 
    public string Key { get; set; } 
    public string Value { get; set; } 
} 

那你乾脆:

XElement rootElement = XElement.Parse(StringOfXml); // or 
XElement rootElement = XElement.Load(FileOfXml); 

GenericNode rootNode = new GenericRode(rootElement); 
+1

我認爲你需要在底行中用'rootNode'替換'root' ... –

相關問題