Help with looping through an XML in C# - c#

I have an xml that looks like this
<words>
<word>word1</word>
<word>word2</word>
<word>word3</word>
<word>word4</word>
</words>
I would like to loop through the "word" tags and just output the innertext for now.
how would I do this?
here is what i am doing now but is says the list of nodes count is 1
string _badWordFileDocPath = //my file path;
XmlDocument badWordDoc = new XmlDocument();
badWordDoc.Load(_badWordFileDocPath);
XmlElement root = badWordDoc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("/words");
foreach(XmlNode node in nodes)
{
Console.WriteLine(node.InnerText);
}
Thanks!

You are selecting the root words node itself, rather than the child word nodes. Add /word to your XPath:
XmlNodeList nodes = root.SelectNodes("/words/word");

You need to move down the node tree one more layer:
foreach(XmlNode node in nodes)
{
XmlNodeList innerNodes = node.SelectNodes("/word");
foreach(Xmlnode innerNode in innerNodes )
{
Console.WriteLine(innerNode.InnerText);
}
}

I'd recommend using the classes in System.Xml.Linq for this task:
XElement wordsElement = XElement.Parse(yourXmlText);
var words = from w in wordsElement.Elements("word")
select w.Value;

You are missing /word in your XPath.
You can also use Linq (XDocument) to fetch the data.

Related

Insert a string in a particular position into an other string

I am work on some innerxml of an XML document.
I have to concat several parts.
I have this:
<TRANFSERT><GOOD></GOOD></TRANSFERT>
I want to insert another part, <GOOD></GOOD>, before </TRANSFERT>.
I tried this:
int pos = xmldoc.indexOf("</GOOD>");
StringBuilder sb = new StringBuilder(xmlFinal);
sb.Append(xmlModifiee,pos,xmlModifiee.length);
xmlFinal = sb.ToString();
But it doesn't work.
How can I add a small part of XML in other XML?
You shouldn't interact with XML like with ordinary string.
Use provided System.Xml.XmlDocument or System.Xml.Linq.XDocument classes:
Ordinary XmlDocument single node selection and appending new element to it:
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("YourFile.xml");
XmlNode goodNode = xmlDocument.SelectSingleNode("TRANSFERT/GOOD");
XmlNode nodeToInsert = xmlDocument.CreateElement("INSERTEDNODE");
goodNode.AppendChild(nodeToInsert);
Ordinary XmlDocument iterating by nodes to find necessary (be aware for many-childed nodes) and add new child node to it:
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("YourFile.xml");
foreach (XmlNode rootNode in xmlDocument.ChildNodes)
{
if (rootNode.Name == "TRANSFERT")
{
foreach (XmlNode childNode in rootNode.ChildNodes)
{
if (childNode.Name == "GOOD")
{
XmlNode nodeToInsert = xmlDocument.CreateElement("INSERTEDNODE");
childNode.AppendChild(nodeToInsert);
}
}
}
}
Linq to XML variant:
XDocument xDoc = XDocument.Load("YourFIle.xml");
XElement rootElement = xDoc.Element("TRANSFERT");
XElement goodElement = rootElement.Element("GOOD");
goodElement.Add(new XElement("INSERTEDNODE"));
Simplified Linq to XML variant:
XDocument.Load("YourFIle.xml").Element("TRANSFERT").Element("GOOD").Add(new XElement("INSERTEDNODE"));
EDITED: answering the question, example was rewrited from changing InnerText values to Append/Add new child element to GOOD node.
StringBuilder.Append can only be used to add something to the end of the string. To add something inside the string, use StringBuilder.Insert like this:
sb.Insert(pos, xmlModifiee);

Find an delete specific XML node in C#

I need to find the nodes that have the /CFOP/ tag with 5902 as value, so it always end up being all the itens with the tag /det nItem="x"/ with x being always > 1. So what can i do to make it work?
The XML file: https://drive.google.com/file/d/1-ayEd1PSP9rECeyYesx3dTndInlqNouR/view?usp=sharing
My code is opening the file and trying to erase all the nodes "det nItem > 2", here's what i've done from my researches. But it only opens and save the file without any changes.
using System.Xml;
XmlDocument xml = new XmlDocument();
xml.Load(filename: "C:/Users/A376228/Desktop/xml/ped1.xml");
XmlNodeList nodeList = xml.SelectNodes(xpath: "/infNFe/det[#CFOP=" + 5902 + "]");
foreach (XmlNode node in nodeList)
{
node.ParentNode.RemoveChild(node);
}
xml.Save(filename: "C:/Users/A376228/Desktop/xml/ped1-ready.xml");
Thanks for your time!
Use the XmlNamespaceManager. This code should delete the single node where nItem > 2:
XmlDocument xml = new XmlDocument();
xml.Load(filename: "C:/Users/A376228/Desktop/xml/ped1.xml");
XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(xml.NameTable);
xmlNamespaceManager.AddNamespace("x", "http://www.portalfiscal.inf.br/nfe");
XmlNodeList nodeList = xml.DocumentElement.SelectNodes(xpath: "//x:infNFe/x:det[#nItem > 2]",
xmlNamespaceManager);
foreach (XmlNode node in nodeList)
{
node.ParentNode.RemoveChild(node);
}
xml.Save(filename: "C:/Users/A376228/Desktop/xml/ped1-ready.xml");

how to get the nodes which contain another xml nodes in c#

I have few xml documents. and each document has different nodes. Only thing common is it has _Header and _Table nodes. what i want is to get the parent nodes which contain _Header and _Table nodes.
I want the program to output the following nodes:
_StatementofNetAssets_T1
_StatementofNetAssets_T2
_StatementofNetAssets_T3
How can I do this?
XmlDocument xmlDoc=new XmlDocument();
string xmlname=Server.MapPath("*.xml").ToString();
xmlDoc.Load(xmlname);
XmlNodeList nodeList=xmlDoc.SelectSingleNode("form/Documents").ChildNodes;//get all child nodes
foreach(XmlNode xn in nodeList)
{
XmlElement xe2=(XmlElement)xn;
if(xe2.InnerText=="_Header"||xe2.InnerText=="_Table nodes")
{
XmlNode xn3=xn.ParentNode;
XmlElement xe=(XmlElement)xn3;
Console.WriteLine(xe.InnerText);
}
}
You could use XDocument class and XPath to quickly parse your documents
var elements = XDocument.Load(path).XPathSelectElements("//_Header").Select(q => q.Parent);
You will be needing these namespaces
using System.Linq;
using System.Xml.XPath;

C# code for getting XML element by certain attribute value

I am creating XML document by reading some objects and adding them to proper place (inside xml tree structure). To be able to add it to proper place I need parent XmlNode so I could call parentNode.AppendChild(node);
How can I get XmlNode object if I know value of one of its attributes?
XmlDocument dom = new XmlDocument();
XmlNode parentNode = null;
XmlNode node = dom.CreateElement(item.Title); //item is object that I am writing to xml
XmlAttribute nodeTcmUri = dom.CreateAttribute("tcmUri");
nodeTcmUri.Value = item.Id.ToString();
node.Attributes.Append(nodeTcmUri);
parentNode = ??? - how to get XML node if I know its "tcmUri" attribute value (it is unique value, no other node has same "tcmUri" attribute value)
You can do this using SelectSingleNode function and xpath query as below
XmlNode parentNode = dom.SelectSingleNode("descendant::yournodename[#tcmUri='" + item.Id.ToString() + "']");
Where yournodename has to be replaced with the node name of the parent elements
Try this
XmlDocument doc = new XmlDocument();
doc.LoadXml(content);
XmlNodeList list = doc.SelectNodes("mynode");
foreach (XmlNode item in list)
{
if (item.Attributes["tcmUri"].Value == some_value)
{
// do what you want, item is the element you are looking for
}
}
Use following code:
var nodeList = doc.SelectNodes("<Node Name>[#tcmUri = \"<Value>\"]");
if(list.Count>0)
parentNode = list[0];
Replace <Node Name> with the node name which you want to make the parent node.
Replace the <Value> with the value of tcmUri attribute of the Node which you want to make the parent node.
XPath is your friend :
string xpath = String.Format("//parentTag[#tcmUri='{0}']", "tcmUriValueHere");
//or in case parent node name (parentTag) may varies
//you can use XPath wildcard:
//string xpath = String.Format("//*[#tcmUri='{0}']", "tcmUriValueHere");
parentNode = dom.SelectSingleNode(xpath)

Selecting Particular Node List in XML

<Report xmlns="Microsoft.SystemCenter.DataWarehouse.Report.Alert" xmlns:p1="w3.org/2001/XMLSchema-instance"; Name="Microsoft.SystemCenter.DataWarehouse.Report.Alert" p1:schemaLocation="Microsoft.SystemCenter.DataWarehou?Schema=True">
<Title>Alert Report</Title>
<Created>6/27/2013 9:32 PM</Created>
<StartDate>6/1/2013 9:29 PM</StartDate>
<EndDate>6/27/2013 9:29 PM</EndDate>
<TimeZone>(UTC)</TimeZone>
<Severity>Warning, Critical</Severity>
<Priority>Low, Medium, High</Priority>
<AlertTable>
<Alerts>
<Alert>
<AlertName></AlertName>
<Priority></Priority>
</Alert>
</Alerts>
</AlertTable>
</Report>
So I'm trying to pull down the list of nodes that appear under Alerts child. So /Report/AlertTable/Alerts.
I've done very similar before but in this format it is not working for some reason. Can someone point me out in the right direction?
XmlDocument Log = new XmlDocument();
Log.Load("test.xml");
XmlNodeList myLog = Log.DocumentElement.SelectNodes("//Report/AlertTable/Alerts");
foreach (XmlNode alert in myLog)
{
Console.Write("HERE");
Console.WriteLine(alert.SelectNodes("AlertName").ToString());
Console.WriteLine(alert.SelectNodes("Priority").ToString());
Console.Read();
}
EDIT:
One of the responses had me try to use a bunch of namespace with p1 but had no such luck.
EDIT:
Did not work either:
var name = new XmlNamespaceManager(log.NameTable);
name.AddNamespace("Report", "http://www.w3.org/2001/XMLSchema-instance");
XmlNodeList xml = log.SelectNodes("//Report:Alerts", name);
From a site:
nodename Selects all nodes with the name "nodename"
/ Selects from the root node
// Selects nodes in the document from the current node that match the selection no matter where they are
So I believe
"/AlertTable/Alerts"
would work, as that would be 'from the root node' as well as
"Report/AlertTable/Alerts"
XPath Site
Figured this sucker out.
It had to do with the namespace of "Microsoft.SystemCenter.DataWarehouse.Report.Alert". Changing this to anything but that won't read the XML properly.
XmlDocument log = new XmlDocument();
log.Load(#"C:\Users\barranca\Desktop\test.xml");
// XmlNodeList xml = log.SelectNodes("//ns1:Alerts");
var name = new XmlNamespaceManager(log.NameTable);
name.AddNamespace("ns1", "Microsoft.SystemCenter.DataWarehouse.Report.Alert");
XmlNodeList xml = log.SelectNodes("//ns1:Alert", name);
foreach (XmlNode alert in xml)
{
Console.Write("HERE");
XmlNode test = alert.SelectSingleNode("//ns1:AlertName",name);
string testing = test.InnerText;
Console.Write(testing);
}

Categories

Resources