Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

XML only read the first element

Discussion in 'Scripting' started by Worktrainer, Mar 31, 2021.

  1. Worktrainer

    Worktrainer

    Joined:
    Dec 2, 2019
    Posts:
    5
    Hi All,

    I have an issue where I cannot figure out how to only get the first element where there are more with the same name. I need to get the customer Order number, Email, First and Lastname and product ordered.

    The XML file has one or more <rowprodname> and I only need the first item the rest needs to be ignored for that order number. <orderno>

    With my script I get 5 items in my list, Order Number, Mail, First and Last Name, but I get 8 items in productOrdered.

    Now I need to get the first <rowprodname> for that <orderno> is this possible?

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using System.IO;
    3. using System.Linq;
    4. using System.Xml.Linq;
    5. using System.Xml.Serialization;
    6. using UnityEngine;
    7. using Xml2CSharp;
    8.  
    9. public class PreOrderManager : MonoBehaviour
    10. {
    11.     public TextAsset xml;
    12.     public List<int> orderNumber = new List<int>();
    13.     public List<string> mailAddress = new List<string>();
    14.     public List<string> customerFirstName = new List<string>();
    15.     public List<string> customerLastName = new List<string>();
    16.     public List<string> productOrdered = new List<string>();
    17.  
    18.     void Start()
    19.     {
    20.         var xd = XDocument.Load(@"C:\tmp\Data2.xml");
    21.  
    22.         // Order Numbers
    23.         var orderNumbers = xd.Root
    24.             .Elements("order")
    25.             .Elements("orderno")
    26.             .Select(x => x.Value);
    27.  
    28.         foreach (var x in orderNumbers)
    29.         {
    30.             orderNumber.Add(int.Parse(x));
    31.         }
    32.  
    33.         // Email Adresses
    34.         var email = xd.Root
    35.             .Elements("order")
    36.             .Elements("mailaddress")
    37.             .Select(y => y.Value);
    38.  
    39.         foreach (var y in email)
    40.         {
    41.             mailAddress.Add(y);
    42.         }
    43.              
    44.         // First Name
    45.         var customerNameOne = xd.Root
    46.             .Elements("order")
    47.             .Elements("firstname")
    48.             .Select(z => z.Value);
    49.  
    50.         foreach (var z in customerNameOne)
    51.         {
    52.             customerFirstName.Add(z);
    53.         }
    54.            
    55.         // Last Name
    56.         var customerNameTwo = xd.Root
    57.             .Elements("order")
    58.             .Elements("name")
    59.             .Select(n => n.Value);
    60.  
    61.         foreach (var n in customerNameTwo)
    62.         {
    63.             customerLastName.Add(n);
    64.         }
    65.  
    66.        
    67. // Ordered Products
    68.         var customerItems = xd.Root
    69.             .Elements("order")
    70.             .Elements("rowprodname")
    71.             .Select(p => p.Value);
    72.  
    73.         foreach (var p in customerItems)
    74.         {
    75.             //if (p.Contains("Preorder"))
    76.                 productOrdered.Add(p);
    77.         }
    78.  
    79.     }
    80. }
    Code (CSharp):
    1. <orders>
    2.     <order>
    3.         <orderno><![CDATA[2020001]]></orderno>
    4.         <firstname><![CDATA[Roy]]></firstname>
    5.         <name><![CDATA[Jansen]]></name>
    6.         <mailaddress><![CDATA[roy@jansen.commm]]></mailaddress>
    7.         <orderrow>
    8.             <rowprodname><![CDATA[PreOrder 1x Product One]]></rowprodname>
    9.         </orderrow>
    10.     </order>
    11.         <order>
    12.         <orderno><![CDATA[2020002]]></orderno>
    13.         <firstname><![CDATA[Dennis]]></firstname>
    14.         <name><![CDATA[Hope]]></name>
    15.         <mailaddress><![CDATA[dennis@gmail.com]]></mailaddress>
    16.         <orderrow>
    17.             <rowprodname><![CDATA[PreOrder 1x Product Two]]></rowprodname>
    18.         </orderrow>
    19.         <orderrow>
    20.             <rowprodname><![CDATA[Do Not Get this value! Two]]></rowprodname>
    21.         </orderrow>
    22.     </order>
    23.         <order>
    24.         <orderno><![CDATA[2020003]]></orderno>
    25.         <firstname><![CDATA[Jeroen]]></firstname>
    26.         <name><![CDATA[Vliet]]></name>
    27.         <mailaddress><![CDATA[jeroen@gmail.commm]]></mailaddress>
    28.         <orderrow>
    29.             <rowprodname><![CDATA[PreOrder 1x Product Three]]></rowprodname>
    30.         </orderrow>
    31.         <orderrow>
    32.             <rowprodname><![CDATA[Do Not Get this value! Three]]></rowprodname>
    33.         </orderrow>
    34.     </order>
    35.         <order>
    36.         <orderno><![CDATA[2020004]]></orderno>
    37.         <firstname><![CDATA[Ilse]]></firstname>
    38.         <name><![CDATA[Vis]]></name>
    39.         <mailaddress><![CDATA[ilse@gmail.commm]]></mailaddress>
    40.         <orderrow>
    41.             <rowprodname><![CDATA[PreOrder 1x Product Four]]></rowprodname>
    42.         </orderrow>
    43.     </order>
    44.         <order>
    45.         <orderno><![CDATA[2020005]]></orderno>
    46.         <firstname><![CDATA[Eef]]></firstname>
    47.         <name><![CDATA[Reef]]></name>
    48.         <mailaddress><![CDATA[eef@gmail.commm]]></mailaddress>
    49.         <orderrow>
    50.             <rowprodname><![CDATA[PreOrder 1x Product Five]]></rowprodname>
    51.         </orderrow>
    52.         <orderrow>
    53.             <rowprodname><![CDATA[Do Not Get this value! Five]]></rowprodname>
    54.         </orderrow>
    55.     </order>
    56. </orders>
     
    Last edited: Mar 31, 2021
  2. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,078
    I think you can do it like this (not tested):

    Code (csharp):
    1.  
    2.         var customerItem = xd.Root
    3.             .Elements("order")
    4.             .Descendants()
    5.             .Elements("rowprodname")
    6.             .FirstOrDefault();
    7.  
    8.       productOrdered.Add(customerItem?.Value ?? null);
    However, I would recommend creating a dedicated Order-class which contains all the entries of an order and storing them into one single
    List<Order>
    . This will make your life working with that data much easier.
     
    Worktrainer likes this.
  3. Worktrainer

    Worktrainer

    Joined:
    Dec 2, 2019
    Posts:
    5
    Yes, I get only the first now great.

    But I need to get the first <rowprodname> for every <order>. I don't know much about XML but can I check by <orderno> and then get that single <rowprodname> item for that order?

    thanks for your help :)
     
  4. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,078
    make dedicated order elements... it will be easier to handle:
    Code (CSharp):
    1. public class PreOrderManager : MonoBehaviour
    2. {
    3.     public List<Order> orders = new List<Order>();
    4.  
    5.     void Start()
    6.     {
    7.         var xd = XDocument.Load(@"C:\tmp\Data2.xml");
    8.  
    9.         foreach(var orderElement in xd.Root.Elements())
    10.         {
    11.             Order order = Order.ParseXml(orderElement);
    12.             orders.Add(order);
    13.         }
    14.     }
    15. }
    16.  
    17. [Serializable]
    18. public class Order
    19. {
    20.     public int Number { get; private set; }
    21.     public string MailAddress { get; private set; }
    22.     public string FirstName { get; private set; }
    23.     public string LastName { get; private set; }
    24.  
    25.     public List<string> OrderedProducts { get; private set; }
    26.     public string FirstOrderedProduct => OrderedProducts?.FirstOrDefault();
    27.  
    28.     public static Order ParseXml(XElement xmlOrderNode)
    29.     {
    30.         var order = new Order();
    31.      
    32.         // parse the order no.
    33.         int num = -1;
    34.         int.TryParse(xmlOrderNode.Element("orderno")?.Value, out num);
    35.      
    36.         // set basic properties
    37.         order.Number = num;
    38.         order.MailAddress = xmlOrderNode.Element("mailaddress")?.Value;
    39.         order.FirstName = xmlOrderNode.Element("firstname")?.Value;
    40.         order.LastName = xmlOrderNode.Element("name")?.Value;
    41.  
    42.         // create product orders and add xml values
    43.         order.OrderedProducts = new List<string>();
    44.  
    45.         foreach(var row in xmlOrderNode.Descendants("orderrow"))
    46.         {
    47.             foreach(var prod in row.Descendants("rowprodname"))
    48.             {
    49.                 order.OrderedProducts.Add(prod.Value);
    50.             }
    51.         }
    52.  
    53.         return order;
    54.     }
    55. }
    The code above should convert the xml file into a list of orders containing every value of the xml file.
    This is not tested.

    Note that you will not be able to see the Properties inside the order in Unity's inspector. You can remove the
    { get; private set; }
    part from them to convert them to member variables and see them in the inspector.
     
    Worktrainer likes this.
  5. Worktrainer

    Worktrainer

    Joined:
    Dec 2, 2019
    Posts:
    5
    Thanks a lot for your time! Got it working. :)