-1

I have the Following XML File , How can I obtain the value stored within the tags of a given type (In this Case say of type "FileModel") .. How can I write some code which will get me the values Rep1 and Rep2 . I need these values to run a certain validation in a method

How can I achieve this ?

<?xml version="1.0"?>
<MainClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Items>
    <Settings xsi:type="FileModel">
      <Name>Rep1</Name>
      <IsActive>true</IsActive>
      <IsHidden>false</IsHidden>
    </Settings>
    <Settings xsi:type="FileModel">
      <Name>Rep2</Name>
      <IsActive>true</IsActive>
      <IsHidden>false</IsHidden>
    </Settings> 
   <Settings xsi:type="ServerModel">
      <Name>DelRep</Name>
      <IsActive>false</IsActive>
      <IsHidden>false</IsHidden>
    </Settings>
  </Items>
</MainClass>
  • How are you currently processing the XML? Deserializing via `XmlSerializer`? Parsing with LINQ to XML? Parsing with `XmlDocument`? – dbc Sep 12 '19 at 05:34
  • right now my Entire XML file is stored as a string something like **string wholeContent = File.ReadAllText(this.FilePath);** and that WholeContent is used elsewhere but I think linq to XML would be a better approach in this context –  Sep 12 '19 at 05:39
  • check other answers [here](https://stackoverflow.com/questions/642293/how-do-i-read-and-parse-an-xml-file-in-c), and see if anything can help you – CodeRed Sep 12 '19 at 06:04

3 Answers3

2

You can do this using XPath and a XmlNamespaceManager.

Example (.NetFiddle):

using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;

public class Program
{
    public static void Main()
    {
        var doc = XDocument.Parse(XmlString);
        var namespaceManager = new XmlNamespaceManager(new NameTable());
        namespaceManager.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
        var names = doc.XPathSelectElements(
            "/MainClass/Items/Settings[@xsi:type='FileModel']/Name",
            namespaceManager
        ).Select(e => e.Value);

        Console.WriteLine(String.Join(", ", names));
    }

    private static string XmlString = @"<?xml version=""1.0""?>
<MainClass xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
  <Items>
    <Settings xsi:type=""FileModel"">
      <Name>Rep1</Name>
      <IsActive>true</IsActive>
      <IsHidden>false</IsHidden>
    </Settings>
    <Settings xsi:type=""FileModel"">
      <Name>Rep2</Name>
      <IsActive>true</IsActive>
      <IsHidden>false</IsHidden>
    </Settings> 
   <Settings xsi:type=""ServerModel"">
      <Name>DelRep</Name>
      <IsActive>false</IsActive>
      <IsHidden>false</IsHidden>
    </Settings>
  </Items>
</MainClass>";
}

Which will output: "Rep1, Rep2"

Soc
  • 7,425
  • 4
  • 13
  • 30
0

If you want to use System.Xml:

static void Main(string[] args)
    {
        List<string> result = new List<string>();

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load("myfile.xml");

        XmlNodeList elemList = xmlDoc.GetElementsByTagName("Settings");
        foreach (XmlNode node in elemList)
        {
            if(node.Attributes["xsi:type"].Value == "FileModel")
            {
                foreach (XmlNode item in node.ChildNodes)
                {
                    if (item.Name == "Name")
                        result.Add(item.InnerText);
                } 
            }
        }
    }
Saeid Amini
  • 1,313
  • 5
  • 16
  • 26
0

You can use linq to xml to achieve you desired result. Its more simple than you think. You don't need to have full knowledge of xml or linq.

To retrieve all Name within settings node with type is equal to FileModel.

Code:

var doc = XDocument.Load("Path to xml file");
//Or
var doc = XDocument.Parse(XmlString);

var ns = doc.Root.GetNamespaceOfPrefix("xsi");

var names = doc.Descendants("Items")
    .Elements("Settings")
    .Where(x => x.Attribute(ns + "type").Value == "FileModel")
    .Select(x => x.Element("Name").Value)
    .ToList();


names.ForEach(x => Console.WriteLine(x));

Output:

enter image description here

Or if you want your result in single string then you can join above list with comma(,) like,

var allName = string.Join(", ", names);
Console.WriteLine(allName);

Output:

enter image description here

Online Demo

er-sho
  • 9,581
  • 2
  • 13
  • 26