I am using C# .
I have an xml node with child nodes as follows :
<PriceID>32</PriceID>
<Store_1> 344</Store_1>
<Store_32> 343 </Store_32>
I would like to select all nodes that start with Store
Is there a way I can do it ?
I know there is a way to select nodes with specific names ..
XmlNodeList xnList = quote.SelectNodes("Store_1");
Does anyone know what will help me ?
You can use Linq2Xml
var xDoc = XDocument.Parse(xmlstring);
var stores = xDoc.Descendants()
.Where(d => d.Name.LocalName.StartsWith("Store"))
.ToList();
Related
Please read the code bellow. There I am trying to grab all elements under the <GetSellerListResponse> node, then my goal is to grab TotalNumberOfPages value (currently it's 9 as you can see in the XML).
But my problem is I am getting an error:
System.InvalidOperationException: 'Sequence contains no elements'
Error screenshot is attached for better understanding. Can you tell me what's wrong the way I am trying to grab all elements? Also if possible can you tell how I can grab that 9 from TotalNumberOfPage?
Thanks in advance
C#:
var parsedXML = XElement.Parse(xml);
var AllElements = parsedXML.Descendants("GetSellerListResponse")
.Where(x => x.Attribute("xmlns").Value.Equals("urn:ebay:apis:eBLBaseComponents"))
.First();
XML:
<?xml version="1.0" encoding="UTF-8"?>
<GetSellerListResponse xmlns="urn:ebay:apis:eBLBaseComponents">
<Timestamp>2018-06-20T17:26:29.518Z</Timestamp>
<Ack>Success</Ack>
<Version>1059</Version>
<Build>E1059_CORE_APISELLING_18694654_R1</Build>
<PaginationResult>
<TotalNumberOfPages>9</TotalNumberOfPages>
</PaginationResult>
</GetSellerListResponse>
EDIT: your mistake is the usage of XElement: it is searching for matching elements in the children of <GetSellerListResponse>; that's why you are not getting any result. Change XElement.Parse(xml); to XDocument.Parse(xml);, then the following snippets will work.
You could simply check for the local name:
var AllElements = parsedXML.Descendants().First(x => x.Name.LocalName == "GetSellerListResponse");
I would suggest to use XDocument instead of XElement for parsedXML, because you could shorten the above query to var AllElements = parsedXML.Root;
Another thing you could try is prepending the namespace:
XNamespace ns = "urn:ebay:apis:eBLBaseComponents";
var AllElements = parsedXML.Descendants(ns + "GetSellerListResponse").First();
To answer the question "how to get the number of pages":
var pages = AllElements.Element(ns + "PaginationResult").Element(ns + "TotalNumberOfPages").Value;
I would suggest using the XmlDocument class from System.Xml.
Try the code below:
XmlDocument doc = new XmlDocument();
doc.LoadXml("<GetSellerListResponse xmlns=\"urn:ebay:apis:eBLBaseComponents\"><Timestamp>2018-06-20T17: 26:29.518Z</Timestamp><Ack>Success</Ack><Version>1059</Version><Build>E1059_CORE_APISELLING_18694654_R1</Build><PaginationResult><TotalNumberOfPages>9</TotalNumberOfPages></PaginationResult></GetSellerListResponse>");
XmlNodeList nodeList = doc.GetElementsByTagName("TotalNumberOfPages");
In this case, your nodeList will have just the one element for TotalNumberOfPages and you can access the value by checking
nodeList.FirstOrDefault().InnerText
I have a xml file from which only specific nodes have to be removed. The node name will be given as input from the user. How to remove the specific nodes which have requested from the user?
<Customers>
<Customer>
<id>michle</id>
<address>newjersy</address>
</Customer>
<Customer>
<id>ann</id>
<address>canada</address>
</Customer>
</Customers>
I have tried
var customer = new XElement("customer",
from o in customers
select
new XElement("id", id),
new XElement("address", address)
);
Customer will contain a new node
<Customer>
<id>ann</id>
<address>canada</address>
</Customer>
doc.Element("customers").Elements(customer).ToList().Remove();
but this is not working. How can I remove the element from the xml?
Tom,
Try this...
private static void RemoveNode(string sID)
{
XDocument doc = XDocument.Load(#"D:\\Projects\\RemoveNode.xml");
var v = from n in doc.Descendants("Customer")
where n.Element("id").Value == sID
select n;
v.Remove();
doc.Save(#"D:\\Projects\\RemoveNode.xml");
}
This removed one node when I called it using
RemoveNode("michle");
Hope this helps.
Your main mistake is that you are creating new nodes that not attached with the source document instead of retrieving existed nodes from it.
You can use article "Removing Elements, Attributes, and Nodes from an XML Tree" on MSDN as a guideline to manipulating XML data.
For example, use XNode.Remove() method to delete one node from the tree or Extensions.Remove<T>(this IEnumerable<T> source) where T : XNode to remove every node in the source collection of nodes:
doc.Descendants("Customer")
.Where(x => x.Element("id").Value == id)
.Remove();
But you also need to save document via Save method after that for commit your changes:
doc.Save();
You can remove this way based on id
xdoc.Descendants("Customer")
.Where(x => (string)x.Element("id") == "michle")
.Remove();
Basically what I am trying to do is remove a VSLOC from the list. I don't want to remove everything that belongs to it.
<?xml version="1.0"?>
<GarageNumbers>
<G554>
<id>G554</id>
<VSLOC>V002</VSLOC>
<VSLOC>V003</VSLOC>
<VSLOC>V002</VSLOC>
</G554>
<G566>
<id>G566</id>
<VSLOC>V002</VSLOC>
<VSLOC>V003</VSLOC>
<VSLOC>V002</VSLOC>
</G566>
<G572>
<id>G572</id>
<VSLOC>V001</VSLOC>
<VSLOC>V002</VSLOC>
</G572>
</GarageNumbers>
So, what I have setup is a combobox that I select a G# from which brings up all the VSLOC associated with it in a Listbox. What I need to do is to select a item from the list box and remove the line from the listbox and from the xml document using a button. I have all this setup but when I hit the button it deletes G554 and all the elements with in.
So if I want to select V002 from the list in G554 I want it to just remove that VSLOC with that innertext.
XmlDocument xDoc = new XmlDocument();
xDoc.Load(Application.StartupPath + "/xmlData.xml");
foreach (XmlNode xNode in xDoc.SelectNodes("GarageNumbers/G554"))
if (xNode.SelectSingleNode("VSLOC").InnerText == "V002")
xNode.ParentNode.RemoveChild(xNode);
xDoc.Save(Application.StartupPath + "/xmlData.xml");
You should be able to drill down to the desired elements then remove them. For example, assuming your XML is in an XElement, this approach would work:
string targetCategory = "G554";
string vsloc = "V002";
xml.Element(targetCategory)
.Elements("VSLOC")
.Where(e => e.Value == vsloc)
.Remove();
If you're using an XDocument then add the Root property: xml.Root
var xDoc = XDocument.Load(fname);
var node = xDoc.Descendants("VSLOC")
.Where(e => (string)e.Parent.Element("id") == "G554")
.FirstOrDefault();
if (node != null) node.Remove();
xDoc.Save(fname);
I have a large XML file with a lot of these file nodes:
<File>
<Component>Main</Component>
<Path>C:\Logs\Main</Path>
<FileName>logfile1.log</FileName>
</File>
In my C# program I want to select a node with a certain file name, eg in the above example I would like to select the File node where the FileName is logfile1.log. Is there a way I can do this in my C#, or maybe I need to make the FileName as an attribute for each File node, e.g.:
<File name="logfile1.log">...</File>
Could anybody advise me on the best practise here? Thanks for any help!
Using query syntax;
var xml = XDocument.Load("input.xml");
var node = (from file in xml.Descendants("File")
where (string)file.Element("FileName") == "logfile1.log"
select file).Single();
Obviously the call to force the query (Single() in this case) should be swapped out to suit your own app.
XPath query would be a good choice for that. You can use xpath to search for either an element name or an attribute name.
something like:
var doc = new XPathDocument(path);
var xpath = doc.CreateNavigator();
//with element
var node = xpath.SelectSingleNode("//File[FileName='logfile1.log']");
//or with attribute
var node = xpath.SelectSingleNode("//File[#name='logfile1.log']");
Or, if there could be more than one you can use Select to find multiple matches and then iterate them.
var node = xpath.Select("//File...");
var doc = new XmlDocument();
doc.LoadXml(xml); // or Load(path)
var node = doc.SelectSingleNode("//File/FileName[.='logfile1.log']");
(see XPath selection by innertext)
or
var doc = XDocument.Load(path);
var node = doc.Elements("Path").FirstOrDefault(e => (string)e.Element("FileName") == "logfile1.log");
Using old way of doing via XmlDocument,
string xmlstring = "<root><profile><Name>John</Name><Age>23</Age></profile></root>";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlstring);
string childNodes = xmlDoc.SelectSingleNode("root/Profile").InnerXml;
// output of childNodes would be => "<Name>John</Name><Age>23</Age>";
what is the equivalent of doing the above execution in LinQ when you have XElement variable. I see XPathSelectElement method in XElement but it doesn't return the child nodes + Child nodes text. Any Ideas?
I wouldn't use XPath at all for this. I'd use:
XDocument doc = XDocument.Parse(xmlString);
var nodes = doc.Root
.Elements("profile")
.DescendantsAndSelf();
That give the profile nodes and all their descendants. It's not really clear what you're trying to do with the results, but if you can give more details I should be able to come up with the appropriate code.