Kulstad
Kulstad

Reputation: 81

Get XML attribute and value from elements

I am being provided the following XML, with no ability to change the structure:

<ReportSpec>
  <Report ReportName="ReportName1" FilterMode="Container" Destination="EmailToUser:LoggedInUser" Format="PDF" AlertSource="ALL" CriticalStatus="True">
    <Filter Students="ALL" />
  </Report>
  <Report ReportName="ReportName1" FilterMode="Container" Destination="EmailToUserGroup:UserAdmins" Format="PDF" AlertSource="ALL" CriticalStatus="False">
    <Filter TestScore="1234" />
  </Report>
  <Report ReportName="ReportName1" FilterMode="Container" Destination="Dir:\\net.path.com\reports" Format="PDF" AlertSource="Failing">
    <Filter Grade="ALL" />
  </Report>
  <Report ReportName="ReportName1" FilterMode="Container" Destination="EmailTo:[email protected],[email protected]" Format="PDF" AlertSource="Failing">
    <Filter Course="Programming" />
  </Report>
</ReportSpec>

I am using C# (.NET 4.5), and need to pick up the attribute name and value of the <FILTER> elements, as they will become part of the app logic later in code (that is, I want to collect TestScore="1234" as an entire string, and use it later on). I am currently using XMLSerializer and StreamReader to load the XML document (but I am willing to change my approach, if need be). I've done the PASTE SPECIAL --> XML to Classes in Visual Studio 2013, but the Filters class that gets created won't allow me to perform a foreach over the elements. Can this be done, and how?

Upvotes: 0

Views: 96

Answers (2)

thcerutti
thcerutti

Reputation: 81

You can use XmlDocument class

using System;
using System.IO;
using System.Xml;

namespace ConsoleApplication1 {
class Program {
    static void Main(string[] args) {
        var file = File.ReadAllText("c:\\temp\\file.xml");
        var xmlFile = new XmlDocument();
        xmlFile.LoadXml(file);

        var filterElements = xmlFile.GetElementsByTagName("Filter");
        foreach (XmlNode filterNode in filterElements) {
            var filterName = filterNode.Attributes[0].Name;
            var filterText = filterNode.Attributes[0].InnerXml;
            var destination = filterNode.ParentNode.Attributes["Destination"].InnerText;
            var message = string.Format("the destination {0} will filter {1} by {2}", destination, filterName, filterText);
            Console.WriteLine(message);
        }
        Console.ReadKey();
    }
}

And the output will be:

the destination EmailToUser:LoggedInUser will filter Students by ALL

the destination EmailToUserGroup:UserAdmins will filter TestScore by 1234

the destination Dir:\net.path.com\reports will filter Grade by ALL

the destination EmailTo:[email protected],[email protected] will filter Course by Programming

Upvotes: 1

jdweng
jdweng

Reputation: 34421

Try xml linq

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication2
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XElement reportSpec = XElement.Load(FILENAME);

            var reports = reportSpec.Elements("Report").Where(x => x.Element("Filter").Attribute("TestScore") != null).FirstOrDefault();

            int score = (int)reports.Element("Filter").Attribute("TestScore");
        }
    }
}

Upvotes: 0

Related Questions