I have one XML string, I am trying to read that using C#, but I am not getting child nodes. I am getting entire XML as inner XML string. I am not able to read the nodes. Here is my XML string and my code.
<Filters FilterName="706337_test">
<MemberName>Dorvil</MemberName>
<MemberId />
<ProviderName />
<ProviderId>706337</ProviderId>
<SelectedProjects>5030003</SelectedProjects>
<CNAChartSelected>false</CNAChartSelected>
<OldProject>false</OldProject>
</Filters>
C# code trying to read the XML nodes
XmlDocument xml = new XmlDocument();
xml.LoadXml(xmlstring);
XmlNodeList xnList = xml.SelectNodes("/Filters");
I can see only one child node that too filters, I need to read MemberId, MemberName etc., how to read them?
This is because your string in SelectNodes is wrong:
var xml = new XmlDocument();
xml.LoadXml(xmlstring);
var xnList1 = xml.SelectNodes("/Filters"); //list of 1 element
var xnList2 = xml.SelectNodes("/Filters/*"); //list of 7 elements
foreach (XmlNode node in xnList2)
{
Console.WriteLine(node.OuterXml);
}
Also you can use this:
var xElements = XElement.Parse(xmlstring).Elements();
foreach (var element in xElements)
{
Console.WriteLine(element);
}
You need to tell the app which nodes to read..
XmlDocument xml = new XmlDocument();
xml.LoadXml(xmlstring);
XmlNodeList xnList = xml.SelectNodes("/Filters");
foreach (XmlNode node in xnList)
{
string memberName = node["MemberName"].InnerText;
}
This lets the app know to read what is inside the MemberName node.. Do the same for the other nodes and post back your results. Debug as you go to see what you are getting out of each node.
Related
i am reading from an XML file and it pulls the correct data but pulls the data from 2 different nodes due to repeating of the attributes "server", "database" and "user"
When the program runs, it runs through both rather than just the one node i need it to run through. How can i make it just get the data from the node <MySql_Connection_string/>
The code is as follows:
XmlDocument doc = new XmlDocument();
doc.Load("xmlConnection.xml");
foreach (XmlNode node in doc.DocumentElement)
{
string databaseConnection = node.Attributes[0].InnerText;
if (databaseConnection == "MySQL")
{
foreach (XmlElement element in doc.DocumentElement)
{
foreach (XmlNode child in node.SelectNodes("//MySQL_Connection_string"))
{
MySQLServer = element.GetAttribute("Server");
MySQLDatabase = element.GetAttribute("Database");
MySQLUser = element.GetAttribute("user");
MySQLPassword = element.GetAttribute("password");
Console.WriteLine(MySQLServer);
Console.WriteLine(MySQLDatabase);
Console.WriteLine(MySQLUser);
Console.WriteLine(MySQLPassword);
}
}
}
}
The console.writeline is simply to see the outputs
the xml code is
<?xml version="1.0" encoding="utf-8"?>
<Database_Connections>
<MySQL_Connection_string Database_Connection="MySQL" Server="***" Database="littering_detection_jf" user="jordan" password="***" />
<PostgreSQL_Connection_string Database_Connection="postgreSQL" host="***" username="Jordan" password="***" database="intuvision" Port="***" />
<SQL_connection_string Database_Connection="SQL" Server="****" Database="anprdb" user="Jordan" password="***" />
</Database_Connections>
Get rid of all the foreach loops except the inner one:
foreach (XmlElement child in doc.SelectNodes("//MySQL_Connection_string"))
{
MySQLServer = child.GetAttribute("Server");
MySQLDatabase = child.GetAttribute("Database");
MySQLUser = child.GetAttribute("user");
MySQLPassword = child.GetAttribute("password");
Console.WriteLine(MySQLServer);
Console.WriteLine(MySQLDatabase);
Console.WriteLine(MySQLUser);
Console.WriteLine(MySQLPassword);
break; // not interested in any additional MySQL_Connection_string elements
}
This assumes that doc.SelectNodes("//MySQL_Connection_string") returns only XML elements, no other types of nodes which is the case here, so I replaced your XmlNode child by XmlElement child.
I have the following code:
XmlDocument doc = //A ton of code that generates the document"
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("ElementINeed");
string ElementINeedValue;
foreach(XmlElement node in nodes)
{
ElementINeedValue = node.Value;
}
When I debug the code, node.Value > innerText holds the correct information I'm trying to get from the XML document. Problem is I can't save it, ElementINeedValue remains null
I have xml file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><SENT_110 xmlns:ns2="http://www.mf.gov.pl/SENT/2017/01/18/STypes.xsd" xmlns="http://www.mf.gov.pl/SENT/2017/01/18/SENT_110.xsd"><SentNumber>SENT20180416000032</SentNumber><KeyNumber><ns2:SenderKey>KS-28YM</ns2:SenderKey><ns2:RecipientKey>KR-52DH</ns2:RecipientKey><ns2:CarrierKey>KD-48WW</ns2:CarrierKey></KeyNumber>
I want to read in separate SenderKey, RecipientKey & CarrierKey.
When i use this code:
XmlTextReader reader = new XmlTextReader(file);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(reader);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ns", xmlDoc.DocumentElement.NamespaceURI);
XmlNodeList nodeList = xmlDoc.SelectNodes("/ns:SENT_110/ns:KeyNumber", nsmgr);
foreach (XmlNode node in nodeList)
{
key = node.InnerText;
MessageBox.Show(key);
}
i've got something like this: KS-28YMKR-52DHKD-48WW, without any separate between key.
How i could read only one key?
Use the following XPath:
"/ns:SENT_110/ns:KeyNumber/*"
It will return all nested nodes to you.
If the structure of the XML is fixed it is rather easy by using XDocument:
var xmlText = "<SENT_110 xmlns:ns2=\"http://www.mf.gov.pl/SENT/2017/01/18/STypes.xsd\" xmlns=\"http://www.mf.gov.pl/SENT/2017/01/18/SENT_110.xsd\"><SentNumber>SENT20180416000032</SentNumber><KeyNumber><ns2:SenderKey>KS-28YM</ns2:SenderKey><ns2:RecipientKey>KR-52DH</ns2:RecipientKey><ns2:CarrierKey>KD-48WW</ns2:CarrierKey></KeyNumber></SENT_110>";
var xml = XDocument.Parse(xmlText);
var nodes = xml.Descendants();
var senderKey = nodes.First(d => d.Name.ToString().EndsWith("SenderKey")).Value;
var recipientKey = nodes.First(d => d.Name.ToString().EndsWith("RecipientKey")).Value;
var carrierKey = nodes.First(d => d.Name.ToString().EndsWith("CarrierKey")).Value;
See HERE for a working snippet. If this is just a part of a bigger XML or the structure can be different maybe some more complex searching is needed.
I have xml as follows:
<Reports>
<report>
<name>By Book</name>
<report_type>book</report_type>
<Object>Count Change</Object>
<Slicers detail="detail">
<Namespace>EOD</Namespace>
<BookNode>HighLevel</BookNode>
<DateFrom>T-2</DateFrom>
<DateTo>T-1</DateTo>
<System>NewSystem</System>
</Slicers>
</report>
</Reports>
I simply want to loop through the value of each element of the Xdocument (pref would be any element under Slicers) but to start with just all elements.
When I run the following:
var slicers = from c in config.Elements("Reports")
select c.Value ;
foreach (var xe in slicers)
{
Console.WriteLine(xe);
}
The output is a single line concatenating all the values together.
"By BookbookCount ChangeEODHighLevelT-2T-1NewSystem"
I want to loop through them one at a time, 'By Book' first, run some code then book etc etc.
I am sure this is simple, but cant get round it. I have tried foreach(Xelement in query) but same resulst
i would do it something like this;
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
//load in your xml here
XmlNodeList xnList = doc.SelectNodes("nodeYou'reLookingFor");
//for getting just the splicers you could do "Reports/report/Slicers"
foreach (XmlNode node in xnList)
string namespace = node["Namespace"].InnerText;
//go through all your nodes here
you're creating a xmldoc, loading your xml into it, creating a list which holds each node in the list (at a specified Xpath), and then looping through each. in the loop you can do whatever you want by referencing
node["nodenamehere"].InnerText
I'm currently working with an XML request, and am trying to create a Reply Document that has multiple child nodes of the same name in the call, so what I'm trying to return is:
<Reply Document>
<ConfirmationItem name = "One">
<ItemDetail />
</ConfirmationItem>
<ConfirmationItem name = "Two">
<ItemDetail />
</ConfirmationItem>
...
<ConfirmationItem name = "Twenty">
<ItemDetail />
</ConfirmationItem>
</Reply Document>
I did a bit of research and found this thread: XmlReader AppendChild is not appending same child value in which the accepted answer was that the OP had to create new Elements to be able to append to the end instead of overwrite the first.
My original code is below, it creates the XmlNode from the incoming Request and appends the result to the XmlDocument itself:
//p_transdoc is the XmlDocument that holds all the items to process.
XmlNodeList nodelst_cnfrm = p_transdoc.SelectNodes("//OrderRequest");
foreach (XmlNode node in nodelst_cnfrm)
{
//this is just an XML Object
XmlNode node_cnfrm_itm = this.CreateElement("ConfirmationItem");
node_cnfrm_itm.Attributes.Append(this.CreateAttribute("name")).InnerText = p_transdoc.Attributes["name"].InnerText;
XmlNode node_itmdtl = this.CreateElement("ItemDetail");
node_cnfrm_itm.AppendChild(node_itmdtl);
//xml_doc is the return XML request
xml_doc.AppendChild(node_cnfrm_itm);
}
So after reading that thread and the answer, I tried to change the code to use a new XmlElement each pass through.
//p_transdoc is the XmlDocument that holds all the items to process.
XmlNodeList nodelst_cnfrm = p_transdoc.SelectNodes("//OrderRequest");
foreach (XmlNode node in nodelst_cnfrm)
{
XmlElement node_cnfrm_itm = new XmlElement();
node_cnfrm_itm = this.CreateElement("ConfirmationItem");
node_cnfrm_itm.Attributes.Append(this.CreateAttribute("name")).InnerText = p_transdoc.Attributes["name"].InnerText;
XmlElement node_itmdtl = new XmlElement();
node_itmdtl = this.CreateElement("ItemDetail");
node_cnfrm_itm.AppendChild(node_itmdtl);
//xml_doc is the return XML request
xml_doc.AppendChild(node_cnfrm_itm);
}
But not only does that not work, it returns a server error. So I've come to you for help. Right now this code is just returning one ConfirmationItem. How would I be able to append the ConfirmationItem to the end of the Document instead of overwrite it, to be able to return as many as were sent in?
(I should point out that this code has been heavily formatted for ease of readability, simplicity, and to reduce clutter. Any typographical errors are purely because of the Asker's internal failure at effective proofreading).
Assuming xml_doc is the xml with the ConfirmationItems you need to create the XmlElements with the new XmlDocument. XmlDocument.CreateElement. Hence I use the Linq extension method OfType<>() here to only return the XmlNode objects of the type XmlElement.
// dummy data
XmlDocument p_transdoc = new XmlDocument();
p_transdoc.LoadXml(#"
<root name='rootAttribute'>
<OrderRequest name='one' />
<OrderRequest name='two' />
<OrderRequest name='three' />
</root>
");
XmlDocument xml_doc = new XmlDocument();
xml_doc.LoadXml("<ReplyDocument />");
foreach (var node in p_transdoc.SelectNodes("//OrderRequest").OfType<XmlElement>())
{
XmlElement node_cnfrm_itm = xml_doc.CreateElement("ConfirmationItem");
node_cnfrm_itm = xml_doc.DocumentElement.AppendChild(node_cnfrm_itm) as XmlElement;
node_cnfrm_itm.SetAttribute("name", node.GetAttribute("name"));
XmlElement node_itmdtl = xml_doc.CreateElement("ItemDetail");
node_itmdtl = node_cnfrm_itm.AppendChild(node_itmdtl) as XmlElement;
}
The method CreateElement returns an XmlElement so you can use the methods SetAttribute and GetAttribute.
The code: p_transdoc.Attributes["name"].InnerText doesn't seem right. If you want to get the attributes for the root element of the document you need to type: p_transdoc.DocumentElement.GetAttribute("name")
IMO this is MUCH easier if you're using Linq to XML.
In Linq to XML this would be similar to (some variables have different names):
// dummy data
var transDoc = XDocument.Parse(#"
<root name='rootAttribute'>
<OrderRequest name='one' />
<OrderRequest name='two' />
<OrderRequest name='three' />
</root>");
var xmlDoc = XDocument.Parse("<ReplyDocument />");
xmlDoc.Root.Add(
transDoc.Root.Elements("OrderRequest").Select(o =>
new XElement("ConfirmationElement",
new XAttribute("name", (string)o.Attribute("name")),
new XElement("ItemDetail"))));
Both examples output:
<ReplyDocument>
<ConfirmationElement name="one">
<ItemDetail />
</ConfirmationElement>
<ConfirmationElement name="two">
<ItemDetail />
</ConfirmationElement>
<ConfirmationElement name="three">
<ItemDetail />
</ConfirmationElement>
</ReplyDocument>