Search code examples
c#winformsxmldocument

How to change from XDocument to XMLDocument Code?


Hey I have two xml files and the following Code:

        DataTable table = new DataTable();

        List<string> headingNames = new List<string>();
        List<string> valueNames = new List<string>();

        //first xml file
        XDocument config = XDocument.Load(configFile);

        Dictionary<string, string> dict = config.Descendants("Columns").FirstOrDefault().Elements()
            .GroupBy(x => (string)x.Attribute("XPath"), y => (string)y.Attribute("Name"))
            .ToDictionary(x => x.Key, y => y.FirstOrDefault());

        //second xml file
        XDocument data = XDocument.Load(dataFile);

        List<XElement> positions = data.Descendants("Position").ToList();

But I have to change it into XMLDocument code.

Here the first XML:

<?xml version="1.0" encoding="utf-8"?>
<ROOT>
 <Columns BaseXPath="//Orders/Position/">
  <Colum XPath="@PositionSK" Name="Position"/>
  <Colum XPath="@PosGroup" Name="Gruppen-Nr"/>
  <Colum XPath="@PosNumber" Name="PositionsNr"/>
  <Colum XPath="@PositionCommercialTypeSK" Name="Status"/>
  <Colum XPath="@BundlePositionSK" Name="BundlePositionSK"/>
  <Colum XPath="@MainPositionSK" Name="MainPositionSK"/>
  <Colum XPath="@SalesAgentPrice" Name="Preis"/>
  <Colum XPath="@Catchword" Name="Suchwort"/> 
  <Colum XPath="@ContentComponentCommSK" Name="IKO"/>
  <Colum XPath="@PositionTypeSK" Name="PositionsTyp"/>
  <Colum XPath="//Advertisement[@AdvertisementSK = PositionAdvertisementRelationship/@AdvertisementSK]/@AdvertisementSK" Name="AdvertisementSK"/>
  <Colum XPath="//Advertisement[@AdvertisementSK = PositionAdvertisementRelationship/@AdvertisementSK]/@AdvertisementTypeSK" Name="Formatvorgabe"/>
 </Columns>
</ROOT>

I want to have all the names with the @ and the "Name": Position, Gruppen-Nr, ...

So in the Dic (from my code) is standing {[@PositionSK, Position]}, {[@PosGroup, Gruppen-Nr]}, ...

So how can I reach the same result with the XMLDocument?

In the next step I have:

        foreach (XElement position in positions.Where(e => e.HasAttributes))
        {
            valueNames.Clear();
            headingNames.Clear();

            foreach (XAttribute attribute in position.Attributes().Where(a => dict.ContainsKey($"@{a.Name.LocalName}")))
            {
                string name = attribute.Name.LocalName;
                string xName = dict["@" + name];
                string value = (string)attribute;

                headingNames.Add(xName);

                valueNames.Add(value);
            }

The output will be a DataTable at a DataGridView. It should search the Names with the @ in another xml file and find their value. But need the code with XMLDocument.. and not with linq.. can anybody help me?


Solution

  • A basic example of this would be:

    List<string> valueNames = new List<string>();
    List<string> headingNames = new List<string>();
    
    XmlDocument doc = new XmlDocument();
    doc.Load("data.xml");
    
    for (int r = 0; r < doc.ChildNodes.Count; r++)
    {
        var currentNode = doc.ChildNodes.Item(r);
        if (currentNode.Name.Equals("ROOT"))
        {
            var columnsNode = currentNode.FirstChild;
    
            for (int i = 0; i < columnsNode.ChildNodes.Count; i++)
            {
                XmlNode child = columnsNode.ChildNodes.Item(i);
    
                for (int j = 0; j < child.Attributes.Count; j++)
                {
                    var attribute = child.Attributes.Item(j);
                    if (attribute.Name.Equals("XPath"))
                    {
                        headingNames.Add(attribute.Value);
                    }
                    else if (attribute.Name.Equals("Name"))
                    {
                        valueNames.Add(attribute.Value);
                    }
                }
            }
        }
    }
    

    Some explanation:

    • Your example XML has no XML Declaration, so we can get the Root Element simply be accessing the FirstChild property.

    • After Edit: Your example XML has now a XML Declaration, but the pattern is the same. For-Loop and accessing Child Elements per Indexer of this loop.

    • The 'Columns' Element can be reached the same way.

    • On the 'Columns' Element we for-loop through all Child Nodes and using the indexer (i) of our loop to get the corresponding element. Why? Because it's an XmlNodeList Object.

    • With our XmlNode child we do the same, but this time not with Child Nodes. Instead we loop through the Attribute Nodes and looking for the correct name.