none
Read xml file with XDocument, get the elements, attributes, ...

    Question

  • Hello,

    How is the best way to read a XML file with XDocument and take the values inside a object.

    If I have a list of Elements and I need the attributes.

    With best regards Markus

    XDocument xml = XDocument.Parse(ret);
    
    string variableContent = xml.Element("Root")?.Element("controlRequest")?.Element("Properties")?.Element("orderProperties")?.Element("orderProperty")?.Attribute("name").Value;
    
    
    var elList = xml.Element("Root")?.Element("controlRequest")?.Element("Properties")?.Elements("orderProperties");
    
    // I need here all elements.
    // How I can get it?
    foreach (var t in elList)
    {
    
    }
    
    
    
    foreach (var node in xml.Descendants())
    {
    	if (node is XElement)
    	{
    		switch (node.Name.LocalName)
    		{
    			case "orderProperties":
    				{
    					if (node.HasElements)
    					{
    						foreach (var nodeProperty in node.Descendants())
    						{
    							if (nodeProperty.HasAttributes)
    							{
    
    							}
    						}
    					}
    				}
    				break;
    			case "orderProperty":
    				if (node.HasAttributes)
    				{
    
    				}
    				break;
    		}
    
    	}
    }
    }
    catch (Exception ex)
    {
    Trace.WriteLine(ex.StackTrace);
    }
    
    

    Tuesday, January 30, 2018 5:53 PM

Answers

  • Hi Markus,

    I am not sure what do you mean by faster, is your project time-critical in parsing xml? I think XDocument may have better performance because it comes later than XmlDocument.

    You can also do what I have posted by XDocument like this:

    FileStream fs = new FileStream("input.xml", FileMode.Open);
    StreamReader sr = new StreamReader(fs);
    
    string s = sr.ReadToEnd();
    
    sr.Close();
    fs.Close();
    
    List<Dictionary<string, string>> orderList = new List<Dictionary<string, string>>();
    XDocument xDocument = XDocument.Parse(s);
    
    //Get all nodes
    List<XNode> xNodes = xDocument.DescendantNodes().ToList();
    foreach (XNode node in xNodes)
    {
        XElement element = node as XElement;
        if (element.Name != "orderProperty") continue;
        Dictionary<string, string> dict = new Dictionary<string, string>();
    
        //For each orderProperty, get all attributes
        foreach (XAttribute attribute in element.Attributes())
        {
            dict.Add(attribute.Name.ToString(), attribute.Value);
        }
        orderList.Add(dict);
    }
    
    
    foreach (Dictionary<string, string> dict in orderList)
    {
        foreach (string key in dict.Keys)
        {
            Console.Write(key + ": " + dict[key] + ", ");
        }
        Console.Write("\n");
    }
    
    Console.ReadKey();

    The result is same as previous post.

    We'd better solve one issue in one thread, for your question about your example project, I will post in the project thread.

    Best Regards,

    Charles He


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Friday, February 9, 2018 3:17 AM

All replies

  • Use https://msdn.microsoft.com/en-us/library/bb342176(v=vs.90).aspx to get your nodes.

    XDocument xml = XDocument.Parse(ret);
    var elList = xml.XDocument.XPathSelectElements ("/Root/controlRequest/Properties/orderProperties");
    
    foreach (var t in elList)
    {
    }

    Tuesday, January 30, 2018 10:12 PM
  • Hello Stefan,
    IEnumerable<XElement> listOrderProperties = xml2.Root.Descendants("orderProperty").ToList();
    foreach (var child in listOrderProperties)
    {
     Trace.WriteLine(string.Format("{0} : {1}", child.Name, child.Attribute("name").Value));
    }

    Yes works well, if you know which elements occur.
    How could you write it down if you didn't know which elements and attributes exist?
    You have an XML input -> |FILTER| output -> the structure with element and attributes.
        
    IEnumerable<XElement> list1 = xml2.XPathSelectElements("./orderProperty");  // works not
    IEnumerable<XElement> list2 = xml2.XPathSelectElements("../orderProperty"); // works not
    IEnumerable<XElement> list3 = xml2.XPathSelectElements("/Root/controlRequest/Properties/orderProperties/orderProperty"); // works well

    Regards Markus

    Wednesday, January 31, 2018 4:46 PM
  • If you want to select all the "orderProperty" elements regardless of their position in your xml file, then instead of using the extension method "XPathSelectElements", that requires a certain knowledge of where to find the elements, rather try the native XDocument method "Descendants(XName)":
    var list4 = xml2.Descendants("orderProperty");
    wizend
    Wednesday, January 31, 2018 6:36 PM
  • Hi Markus Freitag,

    Thank you for posting here.

    For your question, you could try the code below.

     XDocument doc = XDocument.Load("books.xml"); // Or whatever
                //var allElements = doc.Descendants();
    
                XmlReader rdr = XmlReader.Create(new System.IO.StringReader(doc.ToString()));
                while (rdr.Read())
                {
                    if (rdr.NodeType == XmlNodeType.Element)
                    {
                        Console.WriteLine(rdr.LocalName);
                    }
                }
                Console.ReadKey();

    I test the code with a simple xml file.

    <Names>
        <Name>
            <FirstName>John</FirstName>
            <LastName>Smith</LastName>
        </Name>
        <Name>
            <FirstName>James</FirstName>
            <LastName>White</LastName>
        </Name>
    </Names>

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, February 1, 2018 6:42 AM
    Moderator
  • Please rephrase your question and post a concise and complete sample XML.

    Cause you do only XML processing, when you know what elements exists.

    Thursday, February 1, 2018 3:11 PM
  • Hello Wendy and Stefan,
    I have to implement this interface.

    What should I do?
    First create the request.
    Transfer the request, analyze the answer.
    • - XDocument
      - XMLDocument
      - XML Serialize
      Do I have to calculate with time differences for these help classes / Libraries ? 
    What is the best way?
    Request
    <?xml version="1.0" encoding="UTF-8"?>
    <control xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="..\..\ZVEI-XSD\control-1.1.xsd" locale="english" senderID="Hostname-Company-Software-Version">
     <controlRequest requestID="20061027-080000-127" equipment="Labelingmachine-1" operation="Labeling" order="order-123" material="" requesttime="2006-10-27T08:00:00+02:00">
      <properties>
       <orderProperties>
        <orderProperty name="TRACE"/>
        <orderProperty name="NOMINALVALUE"/>
       </orderProperties>
       <operationProperties>
        <operationProperty name="ACTUALVALUE"/>
        <operationProperty name="REJECTVALUE"/>
       </operationProperties>
      </properties>
     </controlRequest>
    </control>
    Response NOK
    <?xml version="1.0" encoding="UTF-8"?>
    <control xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="..\..\ZVEI-XSD\control-1.1.xsd" locale="english" senderID="Hostname-Company-Software-Version">
     <controlResponse responseToRequestID="20061027-080000-127" equipment="Labelingmachine-1" operation="Labeling" order="order-123" material="product-1" responsetime="2006-10-27T08:00:01+02:00" state="nok" description="Could not find operationProperty ACTUALVALUE for order order-123 in the database!">
      <properties>
       <orderProperties>
        <orderProperty name="TRACE" value="true" state="ok"/>
        <orderProperty name="NOMINALVALUE" value="1000" UnitOfMeasure="pcs" state="ok"/>
       </orderProperties>
       <operationProperties>
        <operationProperty name="ACTUALVALUE" value="" state="nok"/>
        <operationProperty name="REJECTVALUE" value="1" UnitOfMeasure="pcs" state="ok"/>
       </operationProperties>
      </properties>
     </controlResponse>
    </control>
    Response OK
    <?xml version="1.0" encoding="UTF-8"?>
    <control xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="..\..\ZVEI-XSD\control-1.1.xsd" locale="english" senderID="Hostname-Company-Software-Version">
     <controlResponse responseToRequestID="20061027-080000-127" equipment="Labelingmachine-1" operation="Labeling" order="order-123" material="product-1" responsetime="2006-10-27T08:00:01+02:00" state="ok">
      <properties>
       <orderProperties>
        <orderProperty name="TRACE" value="true" state="ok"/>
        <orderProperty name="NOMINALVALUE" value="1000" UnitOfMeasure="pcs" state="ok"/>
       </orderProperties>
       <operationProperties>
        <operationProperty name="ACTUALVALUE" value="137" UnitOfMeasure="pcs" state="ok"/>
        <operationProperty name="REJECTVALUE" value="1" UnitOfMeasure="pcs" state="ok"/>
       </operationProperties>
      </properties>
     </controlResponse>
    </Control>
    With best regards Markus

    Saturday, February 3, 2018 1:48 PM
  • Hi Markus,

    Since we may not know which elements and which attributes in the xml file, I think it's a good way to use XmlDocument in this scenario. I will take below xml doc from your post as an example and get all orderProperty:

    <?xml version="1.0" encoding="UTF-8"?>
    <control xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="..\..\ZVEI-XSD\control-1.1.xsd" locale="english" senderID="Hostname-Company-Software-Version">
     <controlResponse responseToRequestID="20061027-080000-127" equipment="Labelingmachine-1" operation="Labeling" order="order-123" material="product-1" responsetime="2006-10-27T08:00:01+02:00" state="ok">
      <properties>
       <orderProperties>
        <orderProperty name="TRACE" value="true" state="ok"/>
        <orderProperty name="NOMINALVALUE" value="1000" UnitOfMeasure="pcs" state="ok"/>
       </orderProperties>
       <operationProperties>
        <operationProperty name="ACTUALVALUE" value="137" UnitOfMeasure="pcs" state="ok"/>
        <operationProperty name="REJECTVALUE" value="1" UnitOfMeasure="pcs" state="ok"/>
       </operationProperties>
      </properties>
     </controlResponse>
    </control>


    Since we don't know the number of orderProperty and their attributes, I created a List to store all orderProperty and elements of the list are Dictionary to store all attributes(name and value). Code as below:

    static void Main(string[] args)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load("input.xml");
    
        //Get all orderProperty
        XmlNodeList orderNodes = doc.SelectNodes("//orderProperty");
        List<Dictionary<string, string>> orderList = new List<Dictionary<string, string>>();
    
        foreach (XmlNode node in orderNodes)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();
    
            //For each orderProperty, get all attributes
            foreach (XmlAttribute attribute in node.Attributes)
            {
                dict.Add(attribute.Name, attribute.Value);
            }
            orderList.Add(dict);
        }
    
        //Print all orderProperty and all attributes
        foreach (Dictionary<string, string> dict in orderList)
        {
            foreach (string key in dict.Keys)
            {
                Console.Write(key + ": " + dict[key] + ", ");
            }
            Console.Write("\n");
        }
    
        Console.ReadKey();
    
    }

    And the result is:

    You can also get all operationProperty in the same way.


    Best Regards,

    Charles He


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.



    Thursday, February 8, 2018 6:08 AM
  • Hi Charles He,
    Yes, it looks good. I started with XDocument. I use now this for xDocument.
    What is faster?
      XDocument
      XMLDocument
      XML Serialize

    I need xDocument

      I have to send these telegrams via Socket (TCPClient) and evaluate the answer.
      Is not easy, maybe you have or you know an example project

    look here

       
      With best regards Markus
    Thursday, February 8, 2018 6:06 PM
  • Hi Markus,

    I am not sure what do you mean by faster, is your project time-critical in parsing xml? I think XDocument may have better performance because it comes later than XmlDocument.

    You can also do what I have posted by XDocument like this:

    FileStream fs = new FileStream("input.xml", FileMode.Open);
    StreamReader sr = new StreamReader(fs);
    
    string s = sr.ReadToEnd();
    
    sr.Close();
    fs.Close();
    
    List<Dictionary<string, string>> orderList = new List<Dictionary<string, string>>();
    XDocument xDocument = XDocument.Parse(s);
    
    //Get all nodes
    List<XNode> xNodes = xDocument.DescendantNodes().ToList();
    foreach (XNode node in xNodes)
    {
        XElement element = node as XElement;
        if (element.Name != "orderProperty") continue;
        Dictionary<string, string> dict = new Dictionary<string, string>();
    
        //For each orderProperty, get all attributes
        foreach (XAttribute attribute in element.Attributes())
        {
            dict.Add(attribute.Name.ToString(), attribute.Value);
        }
        orderList.Add(dict);
    }
    
    
    foreach (Dictionary<string, string> dict in orderList)
    {
        foreach (string key in dict.Keys)
        {
            Console.Write(key + ": " + dict[key] + ", ");
        }
        Console.Write("\n");
    }
    
    Console.ReadKey();

    The result is same as previous post.

    We'd better solve one issue in one thread, for your question about your example project, I will post in the project thread.

    Best Regards,

    Charles He


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Friday, February 9, 2018 3:17 AM
  • Hello Charles He21,

    >I am not sure what do you mean by faster, is your project time-critical in parsing xml?
    Yes it is time-critical, I must send the request via socket to the server.
    But think this way for analysis is good. Thanks.
    With best regards Markus
    Friday, February 9, 2018 5:34 PM