Find an delete specific XML node in C# - 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");

Related

Reading a XML file using C# not working for some xml files

I need to read following xml file. I've used XML and LINQ but neither of them show any values.I can't find any mistakes on the code.
I've followed This example it's working fine with XML that shown there.
<dataSet>
<transactions>
<trans>1</trans>
<Amount>1000</Amount>
<Name>1000</Name>
<Type>Income</Type>
<Date>2022-04-21T00:00:00+05:30</Date>
</transactions>
</dataSet>
I've use this code.
using System;
using System.Xml;
namespace ReadXMLInCsharp
{
class Program
{
static void Main(string[] args)
{
//create XMLDocument object
XmlDocument xmlDoc = new XmlDocument();
//returns url of main directory which contains "/bin/Debug"
var url = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
//correction in path to point it in Root directory
var mainpath = ("F:\\Education\\Test\\new.xml");
//load xml file
xmlDoc.Load(mainpath);
XmlNodeList nodeList = xmlDoc.DocumentElement.SelectNodes("/dataSet/transactions");
var NodeStr = "";
foreach (XmlNode node in nodeList)
{
NodeStr = NodeStr + "\nTransaction " + node.SelectSingleNode("trans").InnerText;
}
Console.WriteLine(NodeStr);
}
}
}
I'd note this sort of thing is generally much nicer in the more modern LINQ to XML API. It might look something like this (though there are many ways to skin a cat):
XNamespace ns = "tempuri.org/DataSet.xsd";
var doc = XDocument.Load(mainpath);
var lines =
from dataSet in doc.Elements(ns + "dataSet")
from transactions in dataSet.Elements(ns + "transactions")
from trans in transactions.Elements(ns + "trans")
select $"Transaction {trans.Value}";
var nodeStr = string.Join(Environment.NewLine, lines);
Console.WriteLine(nodeStr);
See this fiddle for a working demo.
Your xml DataSet node has a namespace attribute, so you'll either need to remove it or use XmlNamespaceManager to handle it. Here is a fiddle with both:
https://dotnetfiddle.net/EOXtBN
In the first, I load the xml into a string, then use .Replace:
xmlDoc.LoadXml(getXML().Replace(" xmlns='tempuri.org/DataSet.xsd'", ""));
Probably not optimal, because that namespace is probably there for a reason, but it's possible this could be an option for you. It's the one I got to work first.
Second, I use XmlNamespaceManager to handle the parsing. It doesn't add that much overhead:
xmlDoc.LoadXml(getXML());
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ns", "tempuri.org/DataSet.xsd");
nodeList = xmlDoc.DocumentElement.SelectNodes("//ns:DataSet//ns:transactions", nsmgr);
foreach (XmlNode node in nodeList) {
NodeStr = NodeStr + "\nTransaction " + node.SelectSingleNode("ns:trans", nsmgr).InnerText;
}
Also, bear in mind that you can just include ns:trans in the xpath for the nodelist, like so:
nodeList = xmlDoc.DocumentElement.SelectNodes("//ns:DataSet//ns:transactions//ns:trans", nsmgr);
foreach (XmlNode node in nodeList) {
NodeStr = NodeStr + "\nTransaction " + node.InnerText;
}
Console.WriteLine(NodeStr);
And you can use += to clean it up a little more, too:
nodeList = xmlDoc.DocumentElement.SelectNodes("//ns:DataSet//ns:transactions//ns:trans", nsmgr);
foreach (XmlNode node in nodeList) {
NodeStr += "\nTransaction " + node.InnerText;
}
Console.WriteLine(NodeStr);
Let me know if this works for you.
Your XML file have and you are parsing it via dataset. "s" is in lowercasein your code. set it to
XmlNodeList nodeList = xmlDoc.DocumentElement.SelectNodes("/dataSet/transactions");
Also check the path to your XML is correct.

get #NITEmisor: value from XML File c#

I need to get the VALUE #NITEmisor:11984643 how can i Loop using c# thanks for your help.
my first idea is:
XmlDocument doc = new XmlDocument();
doc.Load(#"C:\XML\1A4F032D-F647-4B1B-BD40-9C816037F320.xml");
XmlNodeList nodeList = doc.SelectNodes("/dte:gtdocumento/dte:sat/dte:dte/dte:datosemision/dte:emisor/var[#name='NITEmisor']");
foreach (XmlNode no in nodeList)
enter image description here

Selecting value from first xml child node

I have an XML file that contains multiple URLs for different image file sizes, and I'm trying to get a single url to load into a picture box. My issue is that the child nodes are named similarly, and the parent nodes are named similarly as well. For example, I want to pull the first medium image (ending in SL160_.jpg). See below for XML code
<Items>
<SmallImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL75_.jpg</URL>
</SmallImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL160_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL162_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
</Items>
I've tried using GetElementsByTag, as well as trying to call something like doc.SelectSingleNode("LargeImage").SelectSingleNode("URL").InnerText, and GetElementByID. All of these have given me an Object set to null reference exception.
What can I do to specify that I want the url from the first found MediumImage node?
Use LinqToXMLïĵŒIt is rather simple
string xml = #"<Items>
<SmallImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL75_.jpg</URL>
</SmallImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.01_SL160_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.02_SL162_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
</Items>";
XElement root = XElement.Parse(xml);
var ele = root.Elements("MediumImage").Where(e => e.Element("URL").Value.EndsWith("SL160_.jpg")).FirstOrDefault();
Console.WriteLine(ele);
In addition to Sky Fang's answer, I think the OP wants this:
var firstMedImg = root.Elements("MediumImage").First();
var imgUrl = firstMedImg.Element("URL").Value;
XmlDocument doc = new XmlDocument();
// PATH TO YOUR DOCUMENT
doc.Load("daco.xml");
// Select LIST ALL ELEMENTS SmallImage,MediumImage,LargeImage
XmlNodeList listOfAllImageElements = doc.SelectNodes("/Items/*");
foreach (XmlNode imageElement in listOfAllImageElements)
{
// Select URL ELEMENT
XmlNode urlElement= node.SelectSingleNode("URL");
System.Console.WriteLine(urlElement.InnerText);
}
Console.ReadLine();
If you want to select multiple url's
XmlDocument doc = new XmlDocument();
// PATH TO YOUR DOCUMENT
doc.Load("daco.xml");
// Select LIST ALL ELEMENTS SmallImage,MediumImage,LargeImage
XmlNodeList listOfAllImageElements = doc.SelectNodes("/Items/*");
foreach (XmlNode imageElement in listOfAllImageElements)
{
// Select URL's ELEMENTs
XmlNodeList listOfAllUrlElements = imageElement.SelectNodes("URL");
foreach (XmlNode urlElement in listOfAllUrlElements)
{
System.Console.WriteLine(urlElement.InnerText);
}
}
Console.ReadLine();
if you have specific namespace in your xml file
XmlDocument doc = new XmlDocument();
doc.Load("doc.xml");
XmlNamespaceManager man = new XmlNamespaceManager(doc.NameTable);
// reaplace http://schemas.microsoft.com/vs/2009/dgml with your namespace
man.AddNamespace("x", "http://schemas.microsoft.com/vs/2009/dgml");
// next you have to use x: in your path like this
XmlNodeList node = doc.SelectNodes("/x:Items/x:*, man);

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);
}

Help with looping through an XML in 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.

Categories

Resources