1

I need to format an XML to a given hierarchy from a list (List<>). The list contains, for the banking information, data spread across multiple rows as shown in the image.

enter image description here

The XML output needs to be formatted like this:

<ROOT>
  <DocumentElement>
    <Supplier>
      <Company>STV</Company>
      <Code>000199</Code>
      <Name>TrafTrans</Name>
      <BankAccounts>
        <SupplierBankAccount>
          <Bban>220-012510-63</Bban>
          <Name>B1</Name>
        </SupplierBankAccount>
        <SupplierBankAccount>
          <Bban>RUIL</Bban>
          <Name>RUIL</Name>
        </SupplierBankAccount>
      </BankAccounts>
      <SupplierAddresses>
        <SupplierAddress>
          <Type>PostalAddress</Type>
          <Name>Loc TrafTrans</Name>
          <IsDefault>true</IsDefault>
          <AddressParts>
            <SupplierAddressPart>
              <AddressPartKey>STREET_NAME</AddressPartKey>
              <AddressPartText>Somewhere</AddressPartText>
            </SupplierAddressPart>
            <SupplierAddressPart>
              <AddressPartKey>COUNTRY</AddressPartKey>
              <AddressPartText>SPAIN</AddressPartText>
            </SupplierAddressPart>
          </AddressParts>
        </SupplierAddress>
      </SupplierAddresses>
    </Supplier>
  </DocumentElement>
</ROOT>

I already have a method that converts a list to an XML and returns a string. But the problem is that this only formats one item from the list and there could be additional info in the following items.

public static string SuppliersToXML(List<SupplierItem> supplier)
{
    CultureInfo ci = new CultureInfo("en-US");
    XmlDocument doc = new XmlDocument();
    var root = doc.CreateElement("ROOT");
    var rootNode = doc.AppendChild(root);
    var docElem = doc.CreateElement("DocumentElement");
    var docElemNode = rootNode.AppendChild(docElem);

    foreach (var item in supplier)
    {
        var supplierElem = doc.CreateElement("Supplier");
        var companyElem = (XmlNode)doc.CreateElement("Company");
        companyElem.InnerText = item.Company.ToString();
        //more code...

        supplierElem.AppendChild(companyElem);
        //more code...
        }
    return doc.OuterXml;
}
Mogsdad
  • 44,709
  • 21
  • 151
  • 275
hatsjie
  • 181
  • 10
  • Is it for a website / portal? How about using XSLT transformations? – Vivek Jain Apr 13 '16 at 15:13
  • Building XML with `XmlDocument` is not a pleasant experience. Definitely check out [`XElement`](https://msdn.microsoft.com/library/bb387089) as well. – Jeroen Mostert Apr 13 '16 at 15:49
  • @Vivek Jain it's part of a web api. I will look into XSLT – hatsjie Apr 13 '16 at 16:58
  • @Jeroen Moster XElement i'm going to check as well. A programmer that build the web api used XmlDocument as an example to start, but those cases were much simpler. I can't ask the orignal programmer no more because he's working abroad nowadays – hatsjie Apr 13 '16 at 16:58
  • @hatsjie, my bad. I thought you have an input XML. When I read it again, it seems that you are looking to output XML and not input. Other than `XmlDocument` or `XElement`, you may try `XmlSerializer` also. Have a look at http://stackoverflow.com/a/4123648/1654121. Cheers!! – Vivek Jain Apr 14 '16 at 06:01

1 Answers1

0

I have found the answer myself, it may not be the prettiest code ever written. But it does the job.

public static string SuppliersToXML(List<SupplierItem> supplier)

{

//A distinct select is needed because bank info can be on multiple lines. So first a list is generated with correct info except for bank information
List<SupplierItem> distinctsupplier = supplier
    .GroupBy(p => p.Code)
    .Select(g => g.First())
    .ToList();

CultureInfo ci = new CultureInfo("en-US");
XmlDocument doc = new XmlDocument();
var root = doc.CreateElement("ROOT");
var rootNode = doc.AppendChild(root);
var docElem = doc.CreateElement("DocumentElement");
var docElemNode = rootNode.AppendChild(docElem);

foreach (var item in distinctsupplier)
{
    var supplierElem = doc.CreateElement("Supplier");
    var companyElem = (XmlNode)doc.CreateElement("Company");
    companyElem.InnerText = item.Company.ToString();
    var codeElem = (XmlNode)doc.CreateElement("Code");
    codeElem.InnerText = item.Code.ToString();
    var codeName = (XmlNode)doc.CreateElement("Name");
    codeName.InnerText = item.Name.ToString();

    //supplieridentifier part
    var supplierIdsElem = doc.CreateElement("SupplierIdentifiers");
    var supplierIdElem = doc.CreateElement("SupplierIdentifier");
    var supplierIdValueElem = (XmlNode)doc.CreateElement("SupplierIDValue");
    supplierIdValueElem.InnerText = item.SupplierIDValue;

    //supplieraddress part
    var supplierAddressesElem = doc.CreateElement("SupplierAddresses");
    var supplierAddressElem = doc.CreateElement("SupplierAddress");
    var supplierTypeValueElem = (XmlNode)doc.CreateElement("Type");
    supplierTypeValueElem.InnerText = item.Type;
    var supplierNameValueElem = (XmlNode)doc.CreateElement("Name");
    supplierNameValueElem.InnerText = item.AddressName;
    var supplierDefaultValueElem = (XmlNode)doc.CreateElement("IsDefault");
    supplierDefaultValueElem.InnerText = item.AddressIsDefault;
    //address part
    var AddressPartElem = doc.CreateElement("AddressParts");
    var supplierAddressPartsElem = doc.CreateElement("SupplierAddressPart");
        //Street
    var AddressPartElemStreetKeyElem = (XmlNode)doc.CreateElement("AddressPartKey");
    AddressPartElemStreetKeyElem.InnerText = item.AddressStreetKey;
    var AddressPartElemStreetValueElem = (XmlNode)doc.CreateElement("AddressPartText");
    AddressPartElemStreetValueElem.InnerText = item.AddressStreetText;
        //Country
    var AddressPartElemCountryKeyElem = (XmlNode)doc.CreateElement("AddressPartKey");
    AddressPartElemCountryKeyElem.InnerText = item.AddressCountryKey;
    var AddressPartElemCountryValueElem = (XmlNode)doc.CreateElement("AddressPartText");
    AddressPartElemCountryValueElem.InnerText = item.AddressCountryText;

    //add elements to supplierelem
    supplierElem.AppendChild(companyElem);
    supplierElem.AppendChild(codeElem);
    supplierElem.AppendChild(codeName);

    //bankaccounts part
    var bankAccountElem = doc.CreateElement("BankAccounts");
    //select all rows that contain multiple lines, so the bank info can be extracted, for a certain supplier
    var bankInformation = supplier.Where(s => s.Code == item.Code).ToList();

    foreach (var bankitem in bankInformation)
    {
        if (item.Code == bankitem.Code)
        {
            var bankAccountSupplElem = doc.CreateElement("SupplierBankAccount");
            var bankAccountBbanElem = doc.CreateElement("Bban");
            var bankAccountBbanValueElem = (XmlNode)doc.CreateElement("Bban");
            bankAccountBbanValueElem.InnerText = bankitem.Bban;
            var bankAccountNameElem = doc.CreateElement("Name");
            var bankAccountNameValueElem = (XmlNode)doc.CreateElement("Name");
            bankAccountNameValueElem.InnerText = bankitem.BankName;

            var bankAccountElemNode = supplierElem.AppendChild(bankAccountElem);
            var bankAccountSupplElemNode = bankAccountElemNode.AppendChild(bankAccountSupplElem);
            bankAccountSupplElemNode.AppendChild(bankAccountBbanValueElem);
            bankAccountSupplElemNode.AppendChild(bankAccountNameValueElem);

        }
    }

    //add address elements to supplierelem
    var supplierAddressesElemNode = supplierElem.AppendChild(supplierAddressesElem);
    var supplierAddressElemNode = supplierAddressesElemNode.AppendChild(supplierAddressElem);
    supplierAddressElemNode.AppendChild(supplierTypeValueElem);
    supplierAddressElemNode.AppendChild(supplierNameValueElem);
    supplierAddressElemNode.AppendChild(supplierDefaultValueElem);
    //add addressparts to supplieraddressesnode
        //Street
    var AddressPartElemNode = supplierAddressElemNode.AppendChild(AddressPartElem);
    var supplierAddressPartsElemNode = AddressPartElemNode.AppendChild(supplierAddressPartsElem);
    supplierAddressPartsElemNode.AppendChild(AddressPartElemStreetKeyElem);
    supplierAddressPartsElemNode.AppendChild(AddressPartElemStreetValueElem);
        //Country (first reinitialize supplieraddresspart)
    supplierAddressPartsElem = doc.CreateElement("SupplierAddressPart");
    var supplierAddressPartsCountryElemNode = AddressPartElemNode.AppendChild(supplierAddressPartsElem);
    supplierAddressPartsCountryElemNode.AppendChild(AddressPartElemCountryKeyElem);
    supplierAddressPartsCountryElemNode.AppendChild(AddressPartElemCountryValueElem);

    //add all supplierelements to docelemnode
    docElemNode.AppendChild(supplierElem);

}
return doc.OuterXml;

}

hatsjie
  • 181
  • 10