Search code examples
c#xmlxmlserializer

XmlSerializer - Iterating over branches


I have an xml supplied by an external source. I have no say in their design or function.

I can reach the initial branch and read the values as needed. I fear editing as I can't access any of the other branches, and if I start tampering with the main branch I could end up removing any other branch besides the one I can deal with.

My main branch looks as: Container \ Object \ Object \ List \ Object \ Property

as in

<Container>
  <Object>
    <Object>
      <List>
        <Object>
          <Property>

As the data I need to Read and Update, are attributes in <Property>. I have an IntOrderID, FirstName, LastName I'm working with.

What I need is the ability to Read and Update an OrderID, which are located in different branches under:

Container \ Object \ Object(*) \ List \ Object \ Property

I have n branches under Object(*) which are having a <Property> with attribute name=OrderID. Value wise then IntOrderID and OrderID are precisely the same value. Previously I've used a linq read and replace function to do my work. That solution is coming up short.

For my container object I have: EDIT: 18/09/23 I may have had an aha moment.

[XmlRoot(ElementName = "Object")]
public class Object
{
    [XmlElement(ElementName = "Property")]
    public List<Property> Property { get; set; }

    [XmlElement(ElementName = "List")]
    public List List { get; set; }

    [XmlElement(ElementName = "Object")]
    public Object ObjectLvl2 { get; set; }

    [XmlElement(ElementName = "Object")]
    public List<ObjectBranch> ObjectBranch { get; set; }  // TODO: There are n branches from this point.

    public Object() { }
}
[XmlRoot(ElementName = "ObjectBranch")]
public class ObjectBranch
{
    [XmlElement(ElementName = "List")]
    public List List { get; set; }

    public ObjectBranch() { }
}

Edit: I'm using a wrapper to access the serializer, within that I'm using a Discover() to read the values as needed:

/// <summary>
/// Discover the attributes from the xml file.
/// </summary>
public void Discover()
{
    foreach (var item in Container.ObjectLvl1.ObjectLvl2.List.ObjectLvl3.Property)
    {
        switch (item.Name)
        {
            case "IntOrderID":
                IntOrderID = item.Value;
                break;
            case "FirstName":
                FirstName = item.Value;
                break;
            case "LastName":
                LastName = item.Value;
                break;
            case "OrderID":
                OrderID = item.Value;
                break;
            default:
                break;
        }
    }
}

EDIT 05/10/23

My solution came down to

List<XElement> elementOID = xml.Descendants("Property")
    .Where(arg => arg.Attribute("name").Value == "OrderID")
    .ToList();

foreach (var orderID in elementOID)
{
   orderID.Attribute("value").Value = item.Value;
}

Where item refers to a dictionary where I keep each of the replacement values I needed (IntOrderID, Firstname, Lastname, OrderID).

Notes taken from - Update XAttribute Value where XAttribute Name = X


Solution

  •     foreach (var item in replacements)
        {
            switch (item.Key)
            {
                case Patient.PropertyNames.IntOrderID:
                    // IntOrderID
                    var elementIOID = xml.Descendants("Property")
                        .Single(arg => arg.Attribute("name").Value == "IntOrderID");
                    elementIOID.Attribute("value").Value = item.Value;
                    break;
                case Patient.PropertyNames.Patient_FirstName:
                    // Firstname, repeated code.
                    break;
                case Patient.PropertyNames.Patient_LastName:
                    // Lastname, repeated code.
                    break;
                case Patient.PropertyNames.OrderID:
                    // OrderID
                    List<XElement> elementOIDs = xml.Descendants("Property")
                        .Where(arg => arg.Attribute("name").Value == "OrderID")
                        .ToList();
    
                    foreach (var orderID in elementOIDs)
                    {
                        orderID.Attribute("value").Value = item.Value;
                    }
                    break;
                default:
                    break;
            }
        }