0

From this XML with around 10,000 records:

    <?xml version="1.0" encoding="utf-8"?>
    <Home>
       <Kitchen>
          <Pantry>
             <Ingredients>
                <Name>Tomato</Name>
                <Price>
                   <ID>1</ID>
                   <Name>SALES</Name>
                </Price>
                <Cost>
                   <ID>2</ID>
                   <Name>COGS</Name>
                </Cost>
              </Ingredients>
           </Pantry>
        </Kitchen>
    </Home>

I was able to manually code the merging of the parent-child (Price and Cost above) name and values with below code:

    // source programmatically generated
    XElement xml = XElement.Parse(xml.ToString());

    foreach (XElement el in xQuery.Descendants("Price"))
    {
        XElement id = el.Element("ID");
        id.ReplaceWith(new XElement("Price_ID", el.Element("ID").Value));
    
        XElement name = el.Element("Name");
        name.ReplaceWith(new XElement("Price_Name", el.Element("Name").Value));
    
        XElement Price_ID = el.Element("Price_ID");
        XElement Price_Name = el.Element("Price_Name");
    
        el.AddBeforeSelf(Price_ID);
        el.AddBeforeSelf(Price_Name);
    }

    foreach (XElement el in xQuery.Descendants("ItemInventoryRet"))
    {
        if (el.Element("Price") != null)
        {
            XElement Price= el.Element("Price");
            Price.Remove();
        }
    }

    // same manual procedure for Cost element..

The desired result:

    <?xml version="1.0" encoding="utf-8"?>
    <Home>
       <Kitchen>
          <Pantry>
             <Ingredients>
                <Name>Tomato</Name>
                <Price_ID>1</Price_ID>
                <Price_Name>SALES</Price_Name>
                <Cost_ID>2</Cost_ID>
                <Cost_Name>COGS</Cost_Name>
              </Ingredients>
           </Pantry>
        </Kitchen>
    </Home>

Now, I am trying to replicate programmatically the above manual code, and here's what I have so far, please note my error below:

    // source programmatically generated
    XElement xml = XElement.Parse(xml.ToString());

    foreach (XElement xParent in xQuery.Descendants("Ingredients").Nodes())
    {
        if (xParent.HasElements)
        {
            string parentName = xParent.Name.ToString();
    
            foreach (XElement xChild in xParent.DescendantsAndSelf(xParent.Name).Nodes())
            {
                string childName = xChild.Name.ToString();
                string concatName = xParent.Name.ToString() + "_" + xChild.Name.ToString();
    
                XElement child = xChild.Element(childName);
    
                xChild.ReplaceWith(new XElement(concatName, xChild.Value.ToString())); // error here: System.NullReferenceException: 'Object reference not set to an instance of an object.'
                XElement concatElement = xChild.Element(concatName);
                xChild.AddBeforeSelf(concatElement); 
            }
    
            if (xParent.Element(parentName) != null)
            {
                XElement parentEl = xParent.Element(parentName);
                parentEl.Remove();
            }
        }
    }

I am getting an error System.NullReferenceException: 'Object reference not set to an instance of an object.' at child.ReplaceWith() above.

RickyBelmont
  • 619
  • 4
  • 11
  • `xChild.Element(childName)` is asking the child for an element of its own name. Which element did you expect that to find? – Jon Skeet Jul 24 '22 at 07:59
  • I am expecting the child of the Price and Cost (ID and Name). I just followed my manual code `XElement id = el.Element("ID"); id.ReplaceWith(new XElement("Price_ID", el.Element("ID").Value));` – RickyBelmont Jul 24 '22 at 08:03
  • I think I got it! Thanks for the guide. I just need to remove that code you mentioned `XElement child = xChild.Element(childName);` and I should replace it with `xChild.ReplaceWith(new XElement(concatName, xChild.Value.ToString()));` directly. – RickyBelmont Jul 24 '22 at 08:16
  • But I am getting another error message `The Parent is missing!` in this line `xChild.AddBeforeSelf(concatElement);`. I am almost there. – RickyBelmont Jul 24 '22 at 08:18
  • Stack Overflow isn't designed as an interactive debugging service. Please create a new question rather than changing this one as you move from one problem to another. – Jon Skeet Jul 24 '22 at 08:24

0 Answers0