xml XPathSelectElements => to string type - c#

I have the following XML structure:
<?xml version="1.0" encoding="utf-8"?>
<xml>
<root>
<Item>
<taxids>
<string>330</string>
<string>374</string>
<string>723</string>
<string>1087</string>
<string>1118</string>
<string>1121</string>
</taxids>
</Item>
</root>
</xml>
I need to get all the string nodes from the xml file to a string variable, like this:
var query = from ip in doc.XPathSelectElements("xml/root/Item")
where ip.XPathSelectElement("taxid").Value == "723"
select ip.XPathSelectElements("taxids").ToString();
But I am getting the following in one row of the variable query:
"System.Xml.XPath.XPathEvaluator+<EvaluateIterator>d__0`1[System.Xml.Linq.XElement]"
I want to get a string like this:
<taxids><string>330</string><string>374</string><string>723</string><string>1087</string><string>1118</string><string>1121</string></taxids>
Is this possible?
Thanks!

I would suggest you something like:
var values = from ids in doc.XPathSelectElements("/xml/root/Item/taxids")
from id in ids.XPathSelectElements("string")
where id.Value.Contains("723")
select ids.ToString();
var result = string.Join("", values);
The value variable will contain all the taxids, which have at least one string child with value 723.
Another variant, which doesn't use XPath for the children checking:
var values = from ids in doc.XPathSelectElements("/xml/root/Item/taxids")
from id in ids.Elements("string")
where id.Value.Contains("723")
select ids.ToString();
var result = string.Join("\n", values);

var doc = XDocument.Parse(#"<?xml version=""1.0"" encoding=""utf-8""?>
<xml>
<root>
<Item>
<taxids>
<string>330</string>
<string>374</string>
<string>723</string>
<string>1087</string>
<string>1118</string>
<string>1121</string>
</taxids>
</Item>
</root>
</xml>");
var query = doc.XPathSelectElement("xml/root/Item/taxids");
Console.WriteLine(query);

Related

Extract data from xml string

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.

How to get enclosure url with XElement C# Console

I read multiple feed from many sources with C# Console, and i have this code where i load XML From sources:
XmlDocument doc = new XmlDocument();
doc.Load(sourceURLX);
XElement xdoc = XElement.Load(sourceURLX);
How to get enclosure url and show as variable?
If I understand your question correctly (I'm making a big assumption here) - you want to select an attribute from the root (or 'enclosing') tag, named 'url'?
You can make use of XPath queries here. Consider the following XML:
<?xml version="1.0" encoding="utf-8"?>
<root url='google.com'>
<inner />
</root>
You could use the following code to retrieve 'google.com':
String query = "/root[1]/#url";
XmlDocument doc = new XmlDocument();
doc.Load(sourceURLX);
String value = doc.SelectSingleNode(query).InnerText;
Further information about XPath syntax can be found here.
Edit: As you stated in your comment, you are working with the following XML:
<item>
<description>
</description>
<enclosure url="blablabla.com/img.jpg" />
</item>
Therefore, you can retrieve the url using the following XPath query:
/item[1]/enclosure[1]/#url
With xml like below
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>title</title>
<link>https://www.link.com</link>
<description>description</description>
<item>
<title>RSS</title>
<link>https://www.link.com/xml/xml_rss.asp</link>
<description>description</description>
<enclosure url="https://www.link.com/media/test.wmv"
length="10000"
type="video/wmv"/>
</item>
</channel>
</rss>
You will get url by reading attribute
var document = XDocument.Load(sourceURLX);
var url = document.Root
.Element("channel")
.Element("item")
.Element("enclosure")
.Attribute("url")
.Value;
To get multiple urls
var urls = document.Descendants("item")
.Select(item => item.Element("enclosure").Attribute("url").Value)
.ToList();
Using foreach loop
foreach (var item in document.Descendants("item"))
{
var title = item.Element("title").Value;
var link = item.Element("link").Value;
var description = item.Element("description").Value;
var url = item.Element("enclosure").Attribute("url").Value;
// save values to database
}

how to get child element attribute value from xml to linq in c#

<?xml version="1.0" encoding="utf-8" ?>
<Response success="true">
<data>
<class name="getId" classValue=" this is a class value"></class>
</data>
</Response>
string strPath = #"C:\Users\Fale\Documents\practice\xpathNavigator\xpathNavigator\1.xml";
XDocument Xdco = XDocument.Load(strPath);
var list = from i in Xdco.Root.Descendants("Response")
where i.Attribute("success").Value == "true"
select i.Element("data").Element("class").Attribute("classValue").Value;
How to check response is true and then to get attribute value using linq c#?
var list = from i in Xdco.Descendants("Response")
where i.Attribute("success").Value == "true"
select i.Element("data").Element("class").Attribute("classValue").V‌​alue;

Trying to delete an XML Node based on attribute value

I am trying to delete one record from the XML based on some attribute value. My XML structure is given below:
<?xml version="1.0" encoding="utf-8"?>
<Users>
<User>
<UserId>12345</UserId>
<FirstName>abcd</FirstName>
<LastName>efgh</LastName>
<Email>Hello#hello.com</Email>
<IsAdmin>No</IsAdmin>
</User>
<User>
<UserId>67890</UserId>
<FirstName>ijklm</FirstName>
<LastName>nopqr</LastName>
<Email>world#world.com</Email>
<IsAdmin>No</IsAdmin>
</User>
<User>
<UserId>12678</UserId>
<FirstName>stuv</FirstName>
<LastName>wxyz</LastName>
<Email>foo#bar.com</Email>
<IsAdmin>Yes</IsAdmin>
</User>
</Users>
E.g if attribute value is 12345 it should delete the below record from the XML.
<User>
<UserId>12345</UserId>
<FirstName>abcd</FirstName>
<LastName>efgh</LastName>
<Email>Hello#hello.com</Email>
<IsAdmin>No</IsAdmin>
</User>
I tried below code but I am not able to delete anything from the XML.
string path = Server.MapPath("~/XML/users.xml");
XElement xEle = XElement.Load(path);
var qry = from element in xEle.Descendants()
where (string)element.Attribute("UserId").Value == "12345"
select element;
if (qry.Count() > 0)
qry.First().Remove();
xEle.Save(path);
I am unable to figure this out. Any help with be appreciated. Thank you
<UserId>12345</UserId> is a nested sub-element of <User>, not an attribute. See XML attribute vs XML element to see the difference.
Thus you need to do:
var userId = "12345";
var qry = from element in xEle.Descendants("User")
where (string)element.Element("UserId") == userId
select element;
var first = qry.FirstOrDefault();
if (first != null)
first.Remove();
Incidentally, by calling both Count() and First(), you are evaluating your query twice. FirstOrDefault() returns the first matching element, or null if the enumerable is empty, and is thus more efficient.
UserId is not attribute in the XML. Its an element
XElement xEle = XElement.Load("input.xml");
var qry = from element in xEle.Descendants()
where (string)element.Element("UserId") == "12345"
select element;
if (qry.Count() > 0)
qry.First().Remove();
xEle.Save("input.xml");
And in your snippet you are comparing 12345 int with string type

Reading an XML and fetching values in c#

What is the cleanest way to be able to fetch the values of Name, Offset and Length as many as they are in this XML using c#
<?xml version="1.0" encoding="utf-8" ?>
<RecordLayout>
<Field>
<Name>Ali</Name>
<Offset>1</Offset>
<Length>2</Length>
</Field>
<Field>
<Name>Bob</Name>
<Offset>1</Offset>
<Length>2</Length>
</Field>
</RecordLayout>
Using LINQ to XML it can be done like this:
var xmlDocument = XDocument.Load("path");
var elements = xmlDocument
.Root
.Elements("Field")
.Select(x => new
{
Name = (string) x.Element("Name"),
Offset = (int) x.Element("Offset"),
Length = (int) x.Element("Length")
});

Categories

Resources