jaxxbo
jaxxbo

Reputation: 7464

how not to create a xml element if a field of the object does not exist using linq-to-xml

I am creating an xml using Linq to XML, and the values are in a Product object. See below c# code snippet generating the xml:

new XElement(xn + "Products",
                    from p in products
                    select
                        new XElement(xn + "Product",
                            new XElement(xn + "ProductId", p.Id),
                            new XElement(xn + "Name", p.Name),
                            new XElement(xn + "Description", new XCData(p.LongDescription.StripHtml())),
                            new XElement(xn + "CategoryExternalId",
                                from c in categories
                                where c.Name == p.PrimaryCategory
                                select c.CategoryId),
                            new XElement(xn + "UPCs",
                                from s in p.SKU
                                select
                                    new XElement(xn + "UPC", s.UPC))))
                        ));

The challenge is UPCs. I dont want to create the UPCs xml node if there are no UPC entries in products SKU array. i.e. p.SKU above in the code snippet, is an array of string UPC fields. So if not a single UPC field exists i.e. if p.SKU.Count ==0, then I do not want the UPCs xml node elements to be created at all.

See the class model snippet:

public class Product
{
   public string Name { get; set; }
   public string Description { get; set; }
   public List<SKU> SKU { get; set; }
}

public class SKU
{
    public string UPC { get; set; }
    public string Name { get; set; }
    public string Overlap { get; set; }
    public string Productline { get; set; }
}

Upvotes: 0

Views: 247

Answers (1)

MarcinJuraszek
MarcinJuraszek

Reputation: 125650

Place that inside your query:

(p.SKU.Count > 0 ? 
    new XElement("UPCs",
        from s in p.SKU
        select new XElement( "UPC", s.UPC)) :
    null)

I've created a simplified version of your query:

var xml = new XElement("Products",
                    from p in products
                    select
                        new XElement("Product",
                            new XElement("ProductId", p.Id),
                            new XElement("Name", p.Name),
                            (p.SKU.Count > 0 ? new XElement("UPCs",
                                                    from s in p.SKU
                                                    select new XElement("UPC", s.UPC))
                                                : null)));

And for input like that one:

var products = new List<Product> {
    new Product {
        Id = 1,
        Name = "TestName",
        SKU = new List<SKU> {
            new SKU { Name = "test", UPC = "UPC1" },
            new SKU { Name = "test2", UPC = "UPC2" }
        }
    },
    new Product {
        Id = 1,
        Name = "TestName",
        SKU = new List<SKU> { }
    }
};

The output is:

<Products>
  <Product>
    <ProductId>1</ProductId>
    <Name>TestName</Name>
    <UPCs>
      <UPC>UPC1</UPC>
      <UPC>UPC2</UPC>
    </UPCs>
  </Product>
  <Product>
    <ProductId>1</ProductId>
    <Name>TestName</Name>
  </Product>
</Products>

So it's exactly what you're trying to achieve, isn't it?

Upvotes: 2

Related Questions