I have an XML file which is like below:
<CPageDataXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<control id="busRowOAppr2EIDLookUpUserControl" controltype="business">
<field controlvaluetype="single" key="busRowOAppr2EIDLookUpUserControl_txtEID">
<valuefield value="709227">E8 - John Doe</valuefield>
</field>
<field controlvaluetype="hidden_single" key="busRowOAppr2EIDLookUpUserControl_txtEID_Email">
<valuefield value="_JohnDoe#Wonder.com">emailid</valuefield>
</field>
</control>
<control id="busDelegationFromDate123" controltype="business">
<field controlvaluetype="single" key="txtCalanderDateWithImage_UserControl">
<valuefield value="" />
</field>
</control>
</CPageDataXML>
I want to read the value of the valuefield where control id="busRowOAppr2EIDLookUpUserControl"
The C# code is:
This is the code for loading the XML:
XmlDocument xPagedata=new XmlDocument();
XmlNode xnodePagedata = null;
xPagedata.LoadXml(strPageData);
This is the code for SelectSingleNode:
string a = xnodePagedata.SelectSingleNode(//Control[#id='busRowOAppr2EIDLookUpUserControl']).Attributes["Value"].Value;
I have tried to use SelectSingleNode(string) but that is giving me a null reference exception. Kindly suggest how should I go about this one. I am an absolute beginer on XML.
One possible way using the same approach :
string a =
xnodePagedata.SelectSingleNode("//control[#id='busRowOAppr2EIDLookUpUserControl']/field/valuefield/#value")
.Value;
UPDATE :
In case there are multiple <valuefield> in one <control> and you want all values, use SelectNodes() for example :
var values =
xPagedata.SelectNodes("//control[#id='busRowOAppr2EIDLookUpUserControl']/field/valuefield/#value");
foreach (XmlNode value in values)
{
Console.WriteLine(value.Value);
}
You can use XDocument : use Descendants("control") to get all controls then filter them using the Where clause then use SelectMany to get a flattened collection of values of valuefield.
XDocument doc = XDocument.Load(filepath);
var result = doc.Descendants("control")
.Where(i => (string)i.Attribute("id") == "busRowOAppr2EIDLookUpUserControl")
.SelectMany(i => i.Descendants("valuefield")
.Select(j => j.Attribute("value")))
.ToList();
And this is the result:
result Count = 2
[0] {value="709227"}
[1] {value="_JohnDoe#Wonder.com"}
Related
I am having an issue when trying to replace a value of an XElement. I am not sure what I am doing wrong. My simplified xml is as follows
<payload>
<field name="SLUG_LOCATOR">
<value>ORIG VALUE</value>
</field>
</payload>
Here is my query
IEnumerable<XElement> fields =
from el in doc.Descendants("field")
where el.Attribute("name").Value == "SLUG_LOCATOR"
select el;
foreach (XElement el in fields)
{
e.Value = "NEW VALUE";
}
If I check el in the for each statement it says that the Value = ORIG VALUE. So I assumed I could just change that and I would expect to see something like this
<payload>
<field name="SLUG_LOCATOR">
<value>NEW VALUE</value>
</field>
</payload>
But this is what I get and I dont know why
<payload>
<field name="SLUG_LOCATOR">NEW VALUE</field>
</payload>
Any help would be greatly appreciated!
Currently, you're selecting <field> element instead of <value> element. That's why the entire content of <field> get changed to NEW VALUE. You can simply modify the select part of your LINQ for the slightest change to fix the problem :
IEnumerable<XElement> values =
from el in doc.Descendants("field")
where el.Attribute("name").Value == "SLUG_LOCATOR"
select el.Element("value");
Or if you need to remain selecting <field>s, then change the for loop content to :
foreach (XElement el in fields)
{
el.Element("value").Value = "NEW VALUE";
}
You're getting the elements that contain the attribute. Try this to get the value subelements:
select el.Descendants("value");
I have an XML document which is as follows
<meta>
<field type="xs-string" name="Category">جداول</field>
<field type="struct" name="Images">
<field type="xs-string" name="FileName">A00000002.png</field>
<field type="xs-string" name="FileName">B00000002.png</field>
<field type="xs-string" name="FileName">C00000002.png</field>
</field>
</meta>
I want to extract A00000002.png B00000002.png C00000002.png as a list using XDocument. My code at the minute is:
var images = (from title in doc.Root.Elements("field").Where(node => node.Attribute("name").Value.Equals("Images")) select (string)title.Value);
But it only returns a string with all the image names beside each other ... Anyone know how I can get the list of image names, without hacking the string apart?
you can use below menioned code
var node = doc.Descendants("field").Elements("field").Select(p=>p.Value);
so you will get the List of Images Name.
O/P
you can use it like
foreach (var item in node)
{
string value = item.ToString();
}
Use Split() function to get an array of string and convert it to List if necessary: pertinent to your case,
string[] _arrImages = ((string)images).Split([separator])
where separator is a proper delimiter char, e.g. (' ').
String array _arrImages can be converted to List<string> by applying _arrImages.ToList() function if necessary. Rgds,
Try to add Regex.Split to your query result :
XElement rootElement = XDocument.Load(#"YourPath").Root;
var images = (from title in rootElement.Elements()
.Where(node => node.Attribute("name").Value.Equals("Images"))select (string)title.Value);
string[] GroupsItems = Regex.Split((string)images, "png");
The problem lies in the fact that you don't enumerate the Images, but instead return the contents of it, which is the string you have shown.
Try this one:
var images = from title in doc.Root.Elements("field").Where(node => node.Attribute("name").Value.Equals("Images")).Descendants().Where( node => node.Attribute("name").Value.Equals("FileName")) select (string)title.Value;
It walks the sub elements in a second Where.
Try following:
var mynode = doc.Descendants("field").Elements("field").Select(f=>f.Value);
<?xml version="1.0" encoding="UTF-8"?>
<meta>
<field type="xs-string" name="AssetId">TF00000002</field>
<field type="xs-string" name="Title">TitleOfAsset</field>
</meta>
I have this XML loaded in to a XDocument using the function
XDocument doc = XDocument.Parse(xmlData)
However, I want to be able to retrieve the text fields "TF00000002" and "TitleOfAsset" ... How do I go about doing this?
templateMetaData.assetID = doc
.Descendants()
.Where(p => p.Name.LocalName == "AssetId")
.ToString();
returns:
System.Linq.Enumerable+WhereEnumerableIterator`1[System.Xml.Linq.XElement]
Can anyone shine a light on this?
In your query, you are calling ToString on an IEnumerable<XElement> which will never give you the expected result, instead look for field elements under your Root and get their value:
var values = doc.Root
.Elements("field")
.Select(element => (string)element);
If you want to access your values using the name attribute you can use Dictionary:
var values = doc.Root
.Elements("field")
.ToDictionary(x => (string)x.Attribute("name"), x => (string)x);
Then you can access the value of AssetId:
var id = values["AssetId"];
I have this XML code:
<AriaGostarInformation>
<MenuInformation>
<MenuNames Name="0" href="default.aspx">home</MenuNames>
<SubMenuNames parentName="1">
fgfgfgfgs
</SubMenuNames>
<SubMenuNames parentName="3">
</SubMenuNames>
</MenuInformation>
<SliderInformation>
<SliderImageAddress>..\..\Img\Hydrangeas.jpg,</SliderImageAddress>
<SliderImageAddress>..\..\Img\Jellyfish.jpg,</SliderImageAddress>
<SliderImageAddress>..\..\Img\Koala.jpg,</SliderImageAddress>
<SliderImageAddress>..\..\Img\Lighthouse.jpg,</SliderImageAddress>
<SliderImageAddress>..\..\Img\Penguins.jpg,</SliderImageAddress>
<SliderImageAddress>..\..\Img\Tulips.jpg,</SliderImageAddress>
</SliderInformation>
<LastProductInformation>
<Product Name="147">
<Subject>
</Subject>
<ProductImageAddress>http://localhost:1209/ckeditor/plugins/imagebrowser/browser/Hydrangeas.jpg</ProductImageAddress>
<ProductDes>
<p><span style="color:#FFA07A;">qwqweqweqe</span>qwe</p>
<p><span style="font-size:11px;">qweqweqw</span>e</p>
</ProductDes>
</Product>
<Product Name="dsa">
<Subject>salm</Subject>
<ProductImageAddress>http://localhost:1209/ckeditor/plugins/imagebrowser/browser/Hydrangeas.jpg</ProductImageAddress>
<ProductDes>
<p>sdADASDASDASDASDASDASD</p>
<p>ASDASDASDADASDASDASDASDA</p>
<p>ASDASDASDASDASDASDASDASDASD</p>
</ProductDes>
</Product>
</LastProductInformation>
</AriaGostarInformation>
I want select last product node in LastProductInformation and get this node's attribute.
My code is:
XmlDocument xdoc = new XmlDocument();
xdoc.Load(AppDomain.CurrentDomain.BaseDirectory + #"\static\css\xml\data.xml");
XmlNode xparent = xdoc.SelectSingleNode("//LastProductInformation");
var b = xparent.SelectSingleNode("/Product[last()]").Attributes["Name"].Value;
but this returns null. What should I do?
Using LINQ to XML
var value = XDocument.Load("path")
.Descendants("Product")
.Last()
.Attribute("Name").Value;
Also you can use XPath with LINQ to XML
var value = XDocument.Load("path")
.XPathSelectElement("//LastProductInformation/Product[last()]")
.Attribute("Name").Value;
Note: Make sure you have a reference to System.Xml.Linq namespace from your project.
You don't have to change to linq.
var b = xparent.SelectSingleNode("//Product")[last()].Attributes["Name"].Value;
The last() works like an index so should be at the end.
given this xml (just a part..)
<?xml version="1.0" encoding="utf-8"?>
<translations>
<key name="BillOfMaterials">
<translation culture="en-GB"><![CDATA[Bill of materials]]>
</translation>
<translation culture="da-DK"><![CDATA[Materiale liste]]>
</translation>
</key>
<key name="TechnicalDetails">
<translation culture="en-GB">
<![CDATA[Technical details
]]>
</translation>
</key>
..
..
...i'm looking for the simplest solution to look up for instance:
so
string thisTranslation = GetTranslation("BillOfMaterials","en-GB"); //value gets to be "Bill of materials"
I have tried the linq way, but it gets rather messy with too many itherations... especially when a simple xpath is enough in xslt... But I can't seem to just do that
Thanks in advance
Edit:
- xml is physical file
- function may not find anything.....should then just return the original key name
/translations/key[#name="BillOfMaterials"]/translation[#culture="en-GB"]
is the xpath that elsewhere is usable..
I would still use LINQ to XML - there's absolutely no need for it to get messy:
XDocument doc = XDocument.Load("test.xml");
string key = "BillOfMaterials";
var element = doc.Root.Elements("key")
.Where(key => key.Attribute("name").Value == key)
.Elements("translation")
.Where(tr => tr.Attribute("culture").Value == "en-GB")
.FirstOrDefault();
string result = (string) element ?? key;
Personally I find that cleaner than using XPath (even though the XPath is undeniably shorter). It separates each section of the query more distinctly, and also if you need any namespace handling, that would be significantly simpler with LINQ to XML than messing around with namespace managers.
You can use XPathSelectElement extension method set on XElement with your XPath selector:
Load your XML into an XDocument:
var doc = XDocument.Load("path\to\file");
and then search it with XPath:
var translation = (string)doc.XPathSelectElement(string.format("/translations/key[#name=\"{0}\"]/translation[#culture=\"{1}\"]", key, culture));
if(string.IsNullOrEmpty(translation))
translation = key;
return translation;
Get you Xml document in a XmlDocument type. You can do this like:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("<xml>"); // Can be a XML in a string, or filename, etc.
Then you can use XPath with the SelectNodes() and SelectNode() methods.
Like:
XmlNodeList xmlNodes = xmlDoc.SelectNodes("/translations/key[#name=\"BillOfMaterials\"]/translation[#culture=\"en-GB\"]");