XElement multiple root elements

2.4k views Asked by At

I have below XML format to Create by XElement class

XML Source

In Which you can see I have two parent node Service and Catalog. Now when I read from source below is code snippet

XElement rootElement = new XElement("Catalog", new XElement("Service"));//Create a root Element 

foreach (....)// Logic for multiple product element 

XElement productElement = new XElement("Product", new XAttribute("name", Obj.Product));//Read the Product
XElement variantElement = new XElement("Variant", new XAttribute("name",Obj.Variant));//Read variant
XElement skuElement = new XElement("SKU", new XAttribute("name", Obj.SKU));//Read SKU

productElement.Add(variantElement, skuElement);//Add varaint and skuvariant to product
rootElement.Add(productElement);//Add product to root element

But the Output is not expected,below is the output

enter image description here

You can see the second parent node appears as closure at the beginning. I know this line is creating the issue

XElement rootElement = new XElement("Catalog", new XElement("Service"));

but I need two root elements? What is the solution? How can i create?

Please help.

1

There are 1 answers

2
EJoshuaS - Stand with Ukraine On BEST ANSWER

The Service element will always be empty because you never actually add anything to it, you just create it. You add your products to the Catalog element instead of adding them to the Service element.

Also, calling these "roots" isn't correct terminology as a valid XML document can only have one root (so in this case the only root element is Catalog).

Here's the code:

public class Product
    {
        public string ProductName { get; set; }

        public string VariantName { get; set; }

        public string SKU { get; set; }
    }

    private static void CreateDoc(List<Product> list)
    {
        XElement serviceElement = new XElement("Service");
        XElement rootElement = new XElement("Catalog", serviceElement);//Create a root Element 

        // Obviously include the foreach loop
        foreach (Product product in list)
        {
            // Obviously replace these hardcoded string with your actual object values
            XElement productElement = new XElement("Product", new XAttribute("name", product.ProductName));//Read the Product
            XElement variantElement = new XElement("Variant", new XAttribute("name", product.VariantName));//Read variant
            XElement skuElement = new XElement("SKU", new XAttribute("name", product.SKU));//Read SKU

            productElement.Add(variantElement, skuElement);//Add varaint and skuvariant to product

            // Add product to the Service element, NOT to the root. The root is Catalog.
            serviceElement.Add(productElement);
        }

        rootElement.Save("XmlFile.xml");
    }

The main changes are

// Store the Service element is a variable so we can add stuff to it
XElement serviceElement = new XElement("Service");

// ...

// Add to the Service element instead of to Catalog
serviceElement.Add(productElement);

I call it like this:

List<Product> list = new List<Product>
        {
            new Product { ProductName = "SomeName", SKU = "SomeSKU", VariantName = "VariantA" },
            new Product { ProductName = "AnotherProduct", SKU = "AnotherSKU", VariantName = "VariantB" },
            new Product { ProductName = "ProductC", SKU = "SKUc", VariantName = "VariantC" }
        };

        CreateDoc(list);

Here's the resulting XML:

<?xml version="1.0" encoding="utf-8"?>
<!-- Catalog is the root element for this document -->
<Catalog>
  <!-- Service is NOT a root element, even though it's the only child of Catalog -->
  <Service>
    <!-- Each Service element can have an arbitrary number of Product elements -->
    <Product name="SomeName">
      <Variant name="VariantA" />
      <SKU name="SomeSKU" />
    </Product>
    <Product name="AnotherProduct">
      <Variant name="VariantB" />
      <SKU name="AnotherSKU" />
    </Product>
    <Product name="ProductC">
      <Variant name="VariantC" />
      <SKU name="SKUc" />
    </Product>
  </Service>
</Catalog>

Another clarification - in this case Service is not a root element (even though it's the only child of Catalog in this case).