i read about Linq and xml, but i dont know if i do it the right way...
here my XML Configuration File:
<?xml version="1.0" encoding="utf-8"?>
<Configuration>
<Priorities>
<Priority Index="0">Zero</Priority>
<Priority Index="1">One</Priority>
<Priority Index="2">Two</Priority>
<Settings>
<Name>PriorityName</Name>
<DisplayName>PriorityDisplayName</DisplayName>
<Active>true</Active>
<Index>0</Index>
</Settings>
</Priorities>
<Workcenters>
<Workcenter Index="0">TEAM_0</Workcenter>
<Workcenter Index="1">TEAM_1</Workcenter>
<Workcenter Index="2">TEAM_2</Workcenter>
<Settings>
<Name>WorkcentersName</Name>
<DisplayName>WorkcentersDisplayName</DisplayName>
<Active>false</Active>
<Index>1</Index>
</Settings>
</Workcenters>
<ErrorPages>
<ErrorPage>
<Name>Error_1</Name>
<Type>Critical</Type>
</ErrorPage>
<ErrorPage>
<Name>Error_2</Name>
<Type>Normal</Type>
</ErrorPage>
</ErrorPages>
</Configuration>
Now i access all Priorities like this:
//Get Prios
XElement xelement = XElement.Load(xmlPath2);
IEnumerable<XElement> priorities = xelement.Descendants("Priorities");
var prios = priorities.Elements("Priority").ToList();
var settings = priorities.Elements("Settings");
foreach (XElement priority in prios)
{
Console.WriteLine(priority.Attribute("Index").Value);
Console.WriteLine(priority.Value);
}
foreach (XElement setting in settings)
{
Console.WriteLine(setting.Element("Name").Value);
Console.WriteLine(setting.Element("Active").Value);
Console.WriteLine(setting.Element("Index").Value);
Console.WriteLine(setting.Element("DisplayName").Value);
}
is this the right way to access the Elements?
i think there will be a better to read solution.
Can u help me?
thanks
You could use XPathSelectElements extension method.
So your code would look something like:
XElement xelement = XElement.Load(xmlPath2);
foreach (XElement priority in xelement.XPathSelectElements("Priorities/Priority"))
{
Console.WriteLine(priority.Attribute("Index").Value);
Console.WriteLine(priority.Value);
}
foreach (XElement setting in xelement.XPathSelectElements("Priorities/Settings"))
{
Console.WriteLine(setting.Element("Name").Value);
Console.WriteLine(setting.Element("Active").Value);
Console.WriteLine(setting.Element("Index").Value);
Console.WriteLine(setting.Element("DisplayName").Value);
}
Related
I have a XML File as shown below ,
<?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>FileOne</Name>
<IsActive>true</IsActive>
<IsHidden>false</IsHidden>
</Settings>
<Settings xsi:type="FileModel">
<Name>FileTwo</Name>
<IsActive>true</IsActive>
<IsHidden>false</IsHidden>
</Settings>
<Settings xsi:type="ServerModel">
<Name>DelRep</Name>
<IsActive>false</IsActive>
<IsHidden>false</IsHidden>
</Settings>
</Items>
<DirectoryPath>D:\MainFolder</DirectoryPath>
</MainClass>
I am extracting some data using the Following code ,
XDocument File = XDocument.Load(path);
XElement element = File .Root.Elements().Single(x => x.Name == "DirectoryPath");
string usingPath = element.Value;
I have been trying to add a certain validation to the above code such that even in a situation that the xml file is missing the part <DirectoryPath>D:\MainFolder</DirectoryPath> , I would not get the error " sequence contains no matching element ".
Is there a property Similar to may be Path.Exist in C# to validate the presence of an XML element
You could use SingleOrDefault, which returns default value if the element is not found
XElement element = File .Root.Elements().SingleOrDefault(x => x.Name == "DirectoryPath");
if(element != null)
{
string usingPath = element.Value;
}
Use: SignleOrDefault. Then you will get proper XElement or null.
There is no default method to verify whether the given node exists or not.But we can use extension methods to achieve the same.
public static class XElementExtension
{
public static bool HasElement(this XElement xElement, string elementName)
{
return xElement.Elements(elementName).Any();
}
}
// Main
var xmlDocument = XElement.Load(#"TestFile.xml", LoadOptions.None);
string elementName = "DirectoryPath";
bool hasElement = xmlDocument.HasElement(elementName);
if(hasElement)
{
Console.WriteLine(xmlDocument.Elements(elementName).First().Value);
}
Let's say I have an xml string:
<?xml version="1.0" encoding="UTF-8"?>
<Return version="1.0">
<File>1</File>
<URL>2</URL>
<SourceUUID>1191CF90-5A32-4D29-9F90-24B2EXXXXXX0</SourceUUID>
</Return>
and I want to extract the value of SourceUUID, how?
I tried:
XDocument doc = XDocument.Parse(xmlString);
foreach (XElement element in doc.Descendants("SourceUUID"))
{
Console.WriteLine(element);
}
If all you want is the content of the SourceUUID element, and there's only going to be 1 in the XML, you can do this:
XDocument doc = XDocument.Parse(xmlString);
var value = doc.Descendants("SourceUUID").SingleOrDefault()?.Value;
If there are going to be more than one, you can do this:
var values = doc.Descendants("SourceUUID").Select(x => x.Value);
This gives you an enumerable of strings that are the text values of the elements.
My XML looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<something.logger>
<add key="LoggerId" value="8a2ff9ef-d144-4dcb-86d8-6ccaf44def20">
</add>
<add key="FederationId" value="00000000-0000-0000-0000-000000000000" />
</something.logger>
</configuration>
My code:
XmlDocument xml = new XmlDocument();
xml.Load(Some-Valid-Path);
XmlNodeList xnList = xml.SelectNodes("/configuration/something.logger");
I am trying to get the Guid (or value..) of value.
In the end i want to get the string "8a2ff9ef-d144-4dcb-86d8-6ccaf44def20"
Thanks !
Use # at the beginning of attribute name to reference an attribute in XPath. Then you need to cast each item in list as XmlAttribute :
XmlNodeList xnList = doc.SelectNodes("/configuration/something.logger/add[#key='LoggerId']/#value");
foreach (XmlAttribute n in xnList)
{
Console.WriteLine(n.Value);
}
Use /# to access attributes:
XmlNodeList xnList = xml.SelectNodes("/configuration/something.logger/add/#value");
I have XML like this.
<?xml version="1.0" encoding="utf-8" ?>
<config>
<atag>
<element1 att="value" />
<element2 att="othervalue"/>
</atag>
<othertag>
<element1 att="value" />
<element2 att="othervalue"/>
</othertag>
</config>
I want to traverse through the file and find "element1" tag and raplce it with "abc" tag.
Please help. Thank You in advance
In the same file I want to store att value in an array first then raplace the tag name to "abc" . Please help me out
var xml = XDocument.Load(fileName);
foreach (var e in xml.Root.Elements().SelectMany(x => x.Elements("element1")))
{
e.Name = "abc";
}
xml.Save(fileName);
I have an XML file
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="publisher" type="KP.Common.Util.XamlConfigurationSection, KP.Common"/>
</configSections>
<publisher>
<p:Publisher xmlns:p="http://schemas.KP.com/xaml/common/notification">
<p:KPLogSubscriber MinimumImportance="Information" />
<p:EventLogSubscriber MinimumImportance="Warning" Source="KPTTY" Log="Application" />
<p:DatabaseMailSubscriber xmlns="http://schemas.KP.com/xaml/data/ef" MinimumImportance="Error" ProfileName = "" Recipients = "administrator#firm.com" Subject = "KPTTY Error" />
</p:Publisher>
</publisher>
</configuration>
I am trying to read the value of the key Recipients using this code:
XmlDocument config = new XmlDocument();
config.Load(configPath);
XmlNode node = config.SelectSingleNode(#"/*[local-name() = 'configuration']/*[local-name() = 'publisher']/*[local-name() = 'Publisher']/*[local-name() = 'DatabaseMailSubscriber']/#Recipients");
Console.WriteLine(node.Value);
but I get an exception (node is null). Is there something wrong with my Xpath? I am trying to ignore any namespaces that might not be present in the xml.
If it is OK to use Linq2Xml
XDocument xDoc = XDocument.Load(fname);
var recipients = xDoc.Descendants()
.First(d => d.Name.LocalName == "DatabaseMailSubscriber")
.Attribute("Recipients")
.Value;
You forgot to do local-name for "Recipients". "Recipients" attribute have empty prefix meaning its namespace is xmlns="http://schemas.KP.com/xaml/data/ef" as defined on the "DatabaseMailSubscriber" element.
I.e. if you don't care of path you can simple use "//" for "any child:
"//*[local-name() = 'DatabaseMailSubscriber']/#*[local-name() = 'Recipients]"
Note: consider actually using namespace properly... or use XDocument as suggested by L.B.