I have XElement object formated like this :
<Setting guid="3bcedf55-b75f-456b-b90a-a92cbbb022ga">
<PatientFieldList>
<PatientFieldSetting PatientName="UserDecision" PatentFieldLength="64" />
<PatientFieldSetting PatientName="prohibited" PatentFieldLength="128" />
</PatientFieldList>
</Setting>
I have to get values of all attributes in all nodes but I don't know how :/ I tried
xml.Elements("PatientFieldList")
xml.Descendants("PatientsSettingsFieldsList").Where(x => x.Attribute("PatentFieldLength").Value == 64)`
I have a lot of node like that so i wonder if there is easy way to access to these attribute by '[]' or somehow.
Code:
using System;
using System.Linq;
using System.Xml.Linq
var xml = "<Setting ...";
var doc = XElement.Parse(xml);
int i; // for int parse
var q = from node in doc.Descendants("PatientFieldSetting")
let name = node.Attribute("PatientName")
let length = node.Attribute("PatentFieldLength")
select new { Name = (name != null) ? name.Value : "", Length = (length != null && Int32.TryParse(length.Value, out i)) ? i : 0 };
foreach (var node in q)
{
Console.WriteLine("Name={0}, Length={1}", node.Name, node.Length);
}
Output:
Name=UserDecision, Length=64
Name=prohibited, Length=128
This will print out attributes of all nodes which have attributes in your xml:
XDocument doc = //your data
var q = from node in doc.Descendants()
where node.Attributes().Count() > 0
select new {NodeName = node.Name, Attributes = node.Attributes()};
foreach (var node in q)
{
Console.WriteLine( node.NodeName );
foreach (var attribute in node.Attributes)
{
Console.WriteLine(attribute.Name + ":" + attribute.Value);
}
Console.WriteLine();
}
If you only want PatientFieldSetting nodes filter for the name:
from node in doc.Descendants("PatientFieldSetting")
Related
This is a portion of XML I'm trying to parse
<BRTHDATES>
<BRTHDATE value="5/1/1963" code="B"/>
</BRTHDATES>
var birthdates = xmlDoc.XPathSelectElements("/INDV/PERSON/BRTHDATES").Elements().Where(e => e.Name == "BRTHDATE");
xe = birthdates.Elements().Where(e => e.Name == "BRTHDATE");
bbs = from b in birthdates
select new
{
Birthdays = b.FirstAttribute.Value,
Code = b?.Value
};
var status = birthdates.Elements().Where(e => e.Name.LocalName == "BRTHDATE").Single().Value;
When I try to get "Value" from the Element I get an empty string. I can't get anything for the "code" attribute.
It sure seems like this should be a lot easier...
You can try below code. I've already tested through a test project and got the require value.
string personBirthday = string.Empty;
string soapResult = #"<?xml version=""1.0"" encoding=""utf - 8"" ?><INDV> <PERSON> <BRTHDATES><BRTHDATE value = ""5/1/1963"" code = ""B"" /> </BRTHDATES></PERSON></INDV> ";
XmlDocument doc = new XmlDocument();
doc.Load(new StringReader(soapResult));
XmlNodeList person = doc.GetElementsByTagName("BRTHDATES");
if (person[0].ChildNodes.Count > 0)
{
foreach (XmlNode item in person[0].ChildNodes)
{
if (item.Name.Trim().Equals("BRTHDATE"))
{
personBirthday = !string.IsNullOrEmpty(item.Attributes[0].Value) ? item.Attributes[0].Value.Trim() : string.Empty;
}
}
}
Here is the solution
You can select specific Element from a Xml. Just try below sample code
XmlNodeList generalTabNodeList = xmlDocument.SelectNodes("/INDV/PERSON/BRTHDATES");
foreach (XmlNode node in generalTabNodeList)
{
if (node.ChildNodes.Count > 0)
{
string birthdate = !string.IsNullOrEmpty(node.ChildNodes[0].ToString()) ? node.ChildNodes[2].InnerText.ToString() : string.Empty;
}
}
I can't quite follow what you are trying to do, but, this should get you going:
For an XML file that looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<INDV>
<PERSON>
<BRTHDATES>
<BRTHDATE value="5/1/1963" code="B"/>
</BRTHDATES>
</PERSON>
</INDV>
(Note, this is an entire XML document - one that matches your code, not just the snippet you provided (that doesn't match your code))
This code will pick out the value and code attributes:
using (var xmlStream = new FileStream("Test.xml", FileMode.Open))
{
XDocument xmlDocument = XDocument.Load(xmlStream);
var birthDateElements = xmlDocument.XPathSelectElements("/INDV/PERSON/BRTHDATES/BRTHDATE");
var birthDateElement = birthDateElements.FirstOrDefault();
if (birthDateElement != null)
{
var attributes = birthDateElement.Attributes();
var valueAttribute = attributes.Where(a => a.Name == "value");
var codeAttribute = attributes.Where(a => a.Name == "code");
}
}
You can play around with this code to figure out what you want to do. Whatever you do, don't pick out attributes by position, pick them out by name.
I have an XML file and I have to extract all the attribute values from XML. I have tried the below one but I need it in Linq. Can anyone guide me how to do this.
Sample XML
<MapFile>
<Import>
<field name1="BorrowId" name2="EMPLID" />
<field name1="Firstname" name2="COMPLETENAME" />
<field name1="Address" name2="Address" Reference="Location" />
</Import>
<Location>
<Lookup Key="CC" Replace="1" />
<Lookup Key="CE" Replace="2" />
</Location>
</MapFile>
Expected Result
[0]:
CurrentVal = "BorrowId"
NewVal = "EMPLID"
Reference = null
ReferenceList = null
[1]:
CurrentVal = "Firstname"
NewVal = "COMPLETENAME"
Reference = null
ReferenceList = null
[2]:
CurrentVal = "Address"
NewVal = "Address"
Reference = "Location"
ReferenceList = [0]:
Key = "CC"
Value = "1"
[1]:
Key = "CE"
Value = "2"
Code
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#sPath);
var attrValues = xmlDoc.GetElementsByTagName("field");
List<MapFileModel> MapFileMod = new List<MapFileModel>();
foreach (XmlNode x in attrValues)
{
MapFileModel _objMapFile = new MapFileModel();
if (x.Attributes["name1"] != null)
{
_objMapFile.CurrentVal = x.Attributes["name1"] != null ? x.Attributes["name2"].Value : null;
_objMapFile.NewVal = x.Attributes["name2"] != null ? x.Attributes["name2"].Value : null;
_objMapFile.Reference = x.Attributes["Reference"] != null ? x.Attributes["Reference"].Value : null;
}
MapFileMod.Add(_objMapFile);
}
Okay, so it looks like you want something like this, which loads all the field elements in the Import just-below-root element, then loads the reference lists by finding every element which isn't Import.
var doc = XDocument.Load("foo.xml");
var replacements = doc
.Root
.Element("Import")
.Elements("field")
.Select(x => new Replacement {
CurrentValue = (string) x.Attribute("name1"),
NewValue = (string) x.Attribute("name2"),
Reference = (string) x.Attribute("reference")
})
.ToList();
var referenceLists = doc
.Root
.Elements()
.Where(f => f.Name.LocalName != "Import")
.ToDictionary(
x => x.Name.LocalName,
x => x.Elements("Lookup")
.Select(l => new KeyValuePair<string, string>(
(string) l.Attribute("Key"),
(string) l.Attribute("Replace"))
.ToList()
);
You'd then look up the Replacement.Reference in ReferenceLists to get the key/value pair list.
Something like this?
https://forums.asp.net/t/1964585.aspx?how+to+read+xml+elements+using+linq+in+c+net+recursively+
Must be improved but :
string strFilename = "/Message.xml";
strFilename = Server.MapPath(strFilename);
XmlDocument xmlDoc = new XmlDocument();
if (File.Exists(strFilename))
{
XmlTextReader rdrXml = new XmlTextReader(strFilename);
do
{
switch (rdrXml.NodeType)
{
case XmlNodeType.Text:
//Console.WriteLine("{0}", rdrXml.Value);
Response.Write(rdrXml.Value + "<br/>");
break;
}
} while (rdrXml.Read());
}
See below is a generic program that parses the xml string and recursively prints attribute name and value. I hope you can check if the name is a reference value per your requirement and go from over there..
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication9
{
class Program
{
static void Main(string[] args)
{
string xmlstring = #"<MapFile>
<Import>
<field name1=""BorrowId"" name2=""EMPLID"" />
<field name1=""Firstname"" name2=""COMPLETENAME"" />
<field name1=""Address"" name2=""Address"" Reference=""Location"" />
</Import>
<Location>
<Lookup Key=""CC"" Replace=""1"" />
<Lookup Key=""CE"" Replace=""2"" />
</Location>
</MapFile>";
XElement xmlTree = XElement.Parse(xmlstring);
ParseChildElement(xmlTree);
Console.ReadLine();
}
static void ParseChildElement(XElement xmlTree)
{
PrintAttributes(xmlTree);
foreach(XElement element in xmlTree.Elements())
{
ParseChildElement(element);
}
}
static void PrintAttributes(XElement xmlTree)
{
foreach (XAttribute attr in xmlTree.Attributes())
{
string[] attribArray = attr.ToString().Split('=');
if (attribArray.Length > 1)
Console.WriteLine(string.Format(#" {0} = {1}", attr.Name, attr.Value));
}
}
}
}
I have created a XML string and Looping that to get value. But its not entering in foreach loop. But in my other code same loop code is working.
my code is :
XML string:
<SuggestedReadings>
<Suggestion Text="Customer Centricity" Link="http://wdp.wharton.upenn.edu/book/customer-centricity/?utm_source=Coursera&utm_medium=Web&utm_campaign=custcent" SuggBy="Pete Fader�s" />
<Suggestion Text="Global Brand Power" Link="http://wdp.wharton.upenn.edu/books/global-brand-power/?utm_source=Coursera&utm_medium=Web&utm_campaign=glbrpower" SuggBy="Barbara Kahn�s" />
</SuggestedReadings>
Code Is:
string str = CD.SRList.Replace("&", "&");
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(str);
XmlNode SuggestionListNode = xmlDoc.SelectSingleNode("/SuggestedReadings/Suggestion");
foreach (XmlNode node in SuggestionListNode)
{
COURSESUGGESTEDREADING CSR = new COURSESUGGESTEDREADING();
var s = db.COURSESUGGESTEDREADINGS.OrderByDescending(o => o.SRID);
CSR.SRID = (s == null ? 0 : s.FirstOrDefault().SRID) + 1;
CSR.COURSEID = LibId;
CSR.TEXT = node.Attributes.GetNamedItem("Text").Value;
CSR.LINK = node.Attributes.GetNamedItem("Link").Value; ;
CSR.SUGBY = node.Attributes.GetNamedItem("SuggBy").Value; ;
CSR.ACTIVEFLAG = "Y";
CSR.CREATEDBY = CD.CreatedBy;
CSR.CREATEDDATE = DateTime.Now;
db.COURSESUGGESTEDREADINGS.Add(CSR);
}
You should use SelectNodes, not SelectSingleNode, since you are trying to get multiple rows out of the XML document.
Use this:
XmlNodeList SuggestionListNode = xmlDoc.SelectNodes("//Suggestion");
foreach (XmlNode node in SuggestionListNode)
{
}
You can try this.
XDocument xdoc = XDocument.Load("data.xml");
var xmlData = from lv1 in xdoc.Descendants("Suggestion")
select new {
Text = lv1.Attribute("Text").Value,
Link = lv1.Attribute("Link").Value,
SuggBy = lv1.Attribute("SuggBy").Value
};
foreach (var item in xmlData){
// your logic here
}
Im having a problem here with selected index change. My xml file contains module number, module name, assesments, credits etc. What im trying to achieve here is - some course details are loaded into listbox from xml (module name and code) but when user selects a module, label should display how many assessments that module has.
Here is my XML file sample
<module>
<moduleCode>ECWM618</moduleCode>
<moduleTitle>Semantic and Social Web</moduleTitle>
<credits>15</credits>
<semester>2</semester>
<assessmentDetails>
<assessment>
<assessmentName>Coursework1</assessmentName>
<assessmentType>Coursework</assessmentType>
<assessmentWeighting>25</assessmentWeighting>
</assessment>
<assessment>
<assessmentName>Coursework2</assessmentName>
<assessmentType>Coursework</assessmentType>
<assessmentWeighting>25</assessmentWeighting>
</assessment>
<assessment>
<assessmentName>Exam</assessmentName>
<assessmentType>Exam</assessmentType>
<assessmentWeighting>50</assessmentWeighting>
</assessment>
</assessmentDetails>
</module>
And here is the code i got
private void moduleSummaryBox_SelectedIndexChanged(object sender, EventArgs e)
{
// when module from modulelist is selected, it read all indicies assigned to the module.
//!!!!!!!! it reads last node only :(? wtf im tired ...lol
//
// read data from modulelist
string path = Directory.GetCurrentDirectory();
FileStream fs = new FileStream(#"myCourse.xml", FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read);
XmlReader moduleReader = XmlReader.Create(fs);
moduleReader.Read();
while (moduleReader.Read())
{
int assessmentNo = 0;
bool match = false;
moduleReader.MoveToElement();
if (moduleReader.Name == "assessmentName")
{
moduleReader.Read();// reads xml file.
XmlNodeType nType = moduleReader.NodeType; //XmlNodeType Specifies the type of node. If node matches specified name = true.
if (nType == XmlNodeType.Text)// if node type match XmlNodeType ( and there is some text in it) statement becomes true
{
this.assno.Text = (moduleReader.Value.ToString()); //set mcode label to matched node.
}
}
if (moduleReader.Value.ToString() == moduleSummaryBox.Items[moduleSummaryBox.SelectedIndex].ToString())
{
match = true;
}
if (match == true)
{
break;
}
}
}
Help appreciated thank you :)
EDIT:
This is what goes into listbox
moduleSummaryBox.Items.Clear();
XmlDocument doc = new XmlDocument();
doc.Load(#"myCourse.xml");
XmlNodeList levelList = doc.GetElementsByTagName("level"+l_level);
foreach (XmlNode node in levelList)
{
XmlElement moduleElement = (XmlElement)node;
XmlNodeList modules_individ = moduleElement.GetElementsByTagName("module");
foreach (XmlNode nodes in modules_individ)
{
XmlElement moduleSeperator = (XmlElement)nodes;
string ll_moduleCode = moduleSeperator.GetElementsByTagName("moduleCode")[0].InnerText;
string ll_moduleTitle = moduleSeperator.GetElementsByTagName("moduleTitle")[0].InnerText;
moduleSummaryBox.Items.Add(ll_moduleCode+" : " + ll_moduleTitle+" ");
}
}
Can you Try With the code sample below:-
const string xmlString =
"<module><moduleCode>ECWM618</moduleCode><moduleTitle>Semantic and Social Web</moduleTitle><credits>15</credits>" +
"<semester>2</semester><assessmentDetails><assessment><assessmentName>Coursework1</assessmentName><assessmentType>Coursework</assessmentType>" +
"<assessmentWeighting>25</assessmentWeighting></assessment><assessment><assessmentName>Coursework2</assessmentName><assessmentType>Coursework</assessmentType>" +
"<assessmentWeighting>25</assessmentWeighting></assessment><assessment><assessmentName>Exam</assessmentName><assessmentType>Exam</assessmentType><assessmentWeighting>50</assessmentWeighting></assessment></assessmentDetails></module>";
var xml = XElement.Parse(xmlString);
var qry =
xml.Descendants()
.Where(e => e.Name == "moduleCode" && e.Value == "ECWM618")
.Ancestors()
.Descendants()
.Where(e => e.Name == "assessmentDetails")
.Elements("assessment").Count();
Is there a simple way, to get all nodes from an xml document? I need every single node, childnode and so on, to check if they have certain attributes.
Or will I have to crawl through the document, asking for childnodes?
In LINQ to XML it's extremely easy:
XDocument doc = XDocument.Load("test.xml"); // Or whatever
var allElements = doc.Descendants();
So to find all elements with a particular attribute, for example:
var matchingElements = doc.Descendants()
.Where(x => x.Attribute("foo") != null);
That's assuming you wanted all elements. If you want all nodes (including text nodes etc, but not including attributes as separate nodes) you'd use DescendantNodes() instead.
EDIT: Namespaces in LINQ to XML are nice. You'd use:
var matchingElements = doc.Descendants()
.Where(x => x.Attribute(XNamespace.Xmlns + "aml") != null);
or for a different namespace:
XNamespace ns = "http://some.namespace.uri";
var matchingElements = doc.Descendants()
.Where(x => x.Attribute(ns + "foo") != null);
see here: Iterating through all nodes in XML file
shortly:
string xml = #"
<parent>
<child>
<nested />
</child>
<child>
<other>
</other>
</child>
</parent>
";
XmlReader rdr = XmlReader.Create(new System.IO.StringReader(xml));
while (rdr.Read())
{
if (rdr.NodeType == XmlNodeType.Element)
{
Console.WriteLine(rdr.LocalName);
}
}
In my opinion the simplest solution is using XPath. Also this works if you have .NET 2:
var testDoc = new XmlDocument();
testDoc.LoadXml(str);
var tmp = testDoc.SelectNodes("//*"); // match every element
XDocument.Descendants will return you all the nodes in a flat enumerable.
Check out LINQ to XML. That does what you need.
http://www.hookedonlinq.com/LINQtoXML5MinuteOverview.ashx
You can use the SelectMany extension for example.
But if you want to check the values you can just use LINQ to create where-statements.
public void AddWithChildren(XmlNode xnod, Int32 intLevel) //,XmlDocument xmlDoc
{
List<IEnumerable> item = new List<IEnumerable>();
XmlNode xnodWorking;
String strIndent = new string('-', 2 * intLevel);
String strIndent1 = new string('#', 2 * intLevel);
if (xnod.NodeType == XmlNodeType.Element)
{
item.Add(new ListXML(strIndent + xnod.Name, strIndent + xnod.Name, ""));
XmlNamedNodeMap mapAttributes = xnod.Attributes;
foreach (XmlNode xnodAttribute in mapAttributes)
{
item.Add(new ListXML(strIndent1 + xnodAttribute.Name, strIndent1 + xnodAttribute.Name, ""));
}
if (xnod.HasChildNodes)
{
xnodWorking = xnod.FirstChild;
while (xnodWorking != null)
{
AddWithChildren(xnodWorking, intLevel + 1);
xnodWorking = xnodWorking.NextSibling;
}
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
XmlDocument document = new XmlDocument();
string xmlStr;
using (var wc = new WebClient())
{
xmlStr = wc.DownloadString("test.xml");
}
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlStr);
XmlNode xnod = xmlDoc.DocumentElement;
AddWithChildren(xnod, 1);
}
string AttrNameerr = "err";//find error code in xml
XmlReader rdr = XmlReader.Create(new stem.IO.StringReader(somesXMLtring));//somesXMLtring is xml in string variable we want to find attribute in.
while (rdr.Read())
{
if (rdr.NodeType == XmlNodeType.Element)
{
//Found the new element, now check if the required attribute is present or not. if not, ignore, if yes then display the same
string val = rdr.GetAttribute(AttrNameerr);//AttrNameerr is name of attribute we need to get value of which. here we are searching for error code stored as value of 'err' attribute
if (val != null)
textBox.Text = strResult = "error = " + rdr.GetAttribute(AttrNameerr);
}
}