How to get the next and previous node - c#

I am trying to get both the next and previous elements of the current element
Here is the xml
<template id="9">
<tabs>
<tab>
<name>test</name>
<description />
</tab>
<tab>
<name>test3</name>
<description />
</tab>
<tab>
<name>test7</name>
<description />
</tab>
</tabs>
<tabs />
<tabs />
</template>
The current node is the tab with
test3
here is the code i am using
var doc = XDocument.Parse(q.XMLtext);
var tabs = doc.ElementOrDefault("template").ElementOrDefault("tabs").Elements();
var Current = doc.ElementOrDefault("template")
.ElementOrDefault("tabs")
.ElementsOrDefault("tab")
.ElementsOrDefault("name")
.Where(x => x.Value == name);
//get the next and previous nodes here

How about this:
var previous = Current.PreviousNode;
var next = Current.NextNode;
The only issue with this is it will return comments and other things that are nodes, but based on your XML this would still work for you.

Related

Why my code with XDocument in .NET not return any elements? (Problem with XML and XDocument)

I have a problem with the following XML:
<?xml version="1.0" encoding="utf-8"?>
<Report xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ReportName="SearchQueryPerformanceReport_05_24_2022_11_19_51" ReportTime="3/24/2022,5/23/2022" TimeZone="Various" ReportAggregation="Daily" LastCompletedAvailableDay="5/24/2022 10:20:00 AM (GMT)" LastCompletedAvailableHour="5/24/2022 10:20:00 AM (GMT)" PotentialIncompleteData="true" xmlns="http://adcenter.microsoft.com/advertiser/reporting/v5/XMLSchema">
<Table>
<Row>
<AccountName value="fffffff" />
<CampaignName value="dddddddddddddd" />
<CampaignId value="424769594" />
<Clicks value="1" />
<CostPerConversion value="" />
<Ctr value="100.00%" />
<AccountId value="1848" />
<DeviceType value="Computer" />
<AverageCpc value="0.25" />
<AveragePosition value="0.00" />
<BidMatchType value="Exact" />
<AdGroupName value="eeeeeeeeee" />
<AdGroupId value="135899347066" />
<AdId value="84933705" />
<ConversionRate value="0.00%" />
<Keyword value="zusammen at" />
<KeywordId value="84937818" />
<Language value="German" />
<Conversions value="0" />
<Impressions value="1" />
<Spend value="0.25" />
<TimePeriod value="2022-04-13" />
<SearchQuery value="zusammen.at" />
</Row>
</Table>
<Copyright>©2022 Microsoft Corporation. All rights reserved. </Copyright>
</Report>
When I use this code the XML does not return any element.
XDocument doc = XDocument.Parse(LstSearchTermV.XmlContent); var result2 = from s in doc.Descendants("Table");
or
var result2 = from s in doc.Element("Table");
or
var result2 = from s in doc.Elements("Row");
I have tried different ways but nothing.
I test with other XML and have same problem.
Does anyone know why, where is the problem?
Update:
I try it: XDocument Elements return null
It work and I get elements but, when I try to get values is very long code, example:
var ValueElement = el.Element(XName.Get("CampaignId", doc.Root.GetDefaultNamespace().NamespaceName)).Attributes().Where(w => w.Name == "value");
¿Is any code more short or more optimized to get data of XDocument?
Yes, you can definitely write simpler code than that, using the XNamespace type and the various operators and conversions available to create an XName, and using the Attribute method that looks for an attribute with a given name:
// Or XNamespace ns = doc.Root.GetDefaultNamespace()
XNamespace ns = "http://adcenter.microsoft.com/advertiser/reporting/v5/XMLSchema";
var value = el.Element(ns + "CampaignId").Attribute("value");
value will be null if there's no such attribute.

Delete data in XML with C#

I have the following XML File:
<order id="1234">
<users>
<user id="102030" nick="nickname" done="false" />
<user id="123456" nick="nickname" done="false" />
</users>
<machines>
<machine id="123" sd="123" ref="" done="false" />
<machine id="456" sd="456" ref="" done="false" />
<machine id="789" sd="789" ref="" done="false" />
</machines>
</order>
I want to delete the user with the id 102030, so the xml looks like this:
<users>
<user id="123456" nick="nickname" done="false" />
</users>
<machines>
<machine id="123" sd="123" ref="" done="false" />
<machine id="456" sd="456" ref="" done="false" />
<machine id="789" sd="789" ref="" done="false" />
</machines>
</order>
This is my code which doesn't work:
XmlDocument doc = XmlDocument.Load(path);
XmlNodeList nodes = doc.GetElementsByTagName("users");
foreach(XmlNode node in nodes){
foreach(XmlAttribute attribute in node.Attributes){
if(attribute.Name== "id" && attribute.Value == "102030"){
node.RemoveAll();
}
}
}
doc.Save(path);
I am a newbie in C# so I need every help!
Thanks in advance, geibi
XmlNode.RemoveAll() does not remove a node. Instead it:
Removes all the child nodes and/or attributes of the current node.
Thus, instead you need to remove the node from its parent:
node.ParentNode.RemoveChild(node);

c# - Adding new parent node to existing Xml File

I have the following xml file and want to add a new parent node after the last existing node.
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<testsuite id="" name="Test Projekt test">
<node_order />
<details />
<testsuite id="" name="Test Suite 1">
<node_order />
<details />
<testsuite id="" name="Test Suite Operation 2">
<node_order />
<details />
</testsuite>
</testsuite>
</testsuite>
<new node here>
i tryed to use the following code but it didn´t worked
XmlElement testsuite = doc_save.CreateElement("testsuite");
XmlAttribute ID = doc_save.CreateAttribute("id");
XmlAttribute Name = doc_save.CreateAttribute("name");
XmlElement node_order = doc_save.CreateElement("node_order");
XmlElement details = doc_save.CreateElement("details");
doc_save.DocumentElement.AppendChild(testsuite);
testsuite.Attributes.Append(ID);
testsuite.Attributes.Append(Name);
testsuite.AppendChild(node_order);
testsuite.AppendChild(details);
How can I do this?
Expanding on the comment by #hotfix, rename your root element and when I ran your code it was working for me. See the XML and code I was using below.
XML:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<testsuites id="" name="Test Projekt test">
<node_order />
<details />
<testsuite id="" name="Test Suite 1">
<node_order />
<details />
<testsuite id="" name="Test Suite Operation 2">
<node_order />
<details />
</testsuite>
</testsuite>
<testsuite id="" name="">
<node_order />
<details />
</testsuite>
</testsuites>
Code:
XmlDocument document = new XmlDocument();
document.Load(#"your\xml\file");
XmlElement testsuite = document.CreateElement("testsuite");
XmlAttribute ID = document.CreateAttribute("id");
XmlAttribute Name = document.CreateAttribute("name");
XmlElement node_order = document.CreateElement("node_order");
XmlElement details = document.CreateElement("details");
document.DocumentElement.AppendChild(testsuite);
testsuite.Attributes.Append(ID);
testsuite.Attributes.Append(Name);
testsuite.AppendChild(node_order);
testsuite.AppendChild(details);
document.Save(#"your\xml\file");

How to parse XML file in c#

I have a XML that has a structure similar to this one:
<?xml version="1.0" encoding="UTF-8"?>
<CompanyName>
<AttrContainer>
<Attr type="String">
<Name value="'Name'" />
<Value value="'AttrContainer'" />
</Attr>
<SubContainer>
<AttrContainer value="'WSSMetadata'" />
<AttrContainer>
<Attr type="String">
<Name value="'Name'" />
<Value value="'AttrContainer'" />
</Attr>
<SubContainer>
<WSSMetadata value="'afe2e194-0ce7-4bfc-b446-9623e4fe7189'" />
<AttrContainer>
<Attr type="String">
<Name value="'Name'" />
<Value value="'WSSMetadata'" />
</Attr>
<Attr type="Uuid">
<Name value="'scanID'" />
<Value value="afe2e194-0ce7-4bfc-b446-9623e4fe7189" />
</Attr>
<Attr type="String">
<Name value="'imagePath'" />
</Attr>
<Attr type="String">
<Name value="'imagePathHD'" />
</Attr>
<Attr type="String">
<Name value="'imagePathThumbnail'" />
</Attr>
<Attr type="String">
<Name value="'imagePathGrey'" />
<Value value="'Images/afe2e194-0ce7-4bfc-b446-9623e4fe7189_grey.jpg'" />
</Attr>
<Attr type="String">
<Name value="'imagePathGreyHD'" />
<Value value="'Images/afe2e194-0ce7-4bfc-b446-9623e4fe7189_grey_hd.jpg'" />
</Attr>
<Attr type="String">
<Name value="'imagePathGreyThumbnail'" />
<Value value="'Images/afe2e194-0ce7-4bfc-b446-9623e4fe7189_grey_thumbnail.jpg'" />
</Attr>
</AttrContainer>
</SubContainer>
</AttrContainer>
</SubContainer>
</AttrContainer>
</CompanyName>
and I am trying to parse it using this code (Linq to XML)
var xmlContent = File.ReadAllText(filePathName);
var doc = XDocument.Parse(xmlContent);
var attr = doc.Root.Elements("CompanyName");
var x = attr.ToList();
but it x has no element.
My questions:
What is wrong with this code that I am not able to get the CompanyName element?
How can I get list of all <SubContainer> elements?
When I got the list of <SubContainer> elements, how can I read read and change its content?
I think you want this instead:
var attr = doc.Root.Elements("AttrContainer");
.Elements returns child elements of that name. CompanyName is you root node, and you're trying to search for its children which are AttrContainer.
What is wrong with this code that I am not able to get the companyname element?
The root element of your xml is CompanyName. So what your code is doing, it's essentially asking 'give me all CompanyName elements that are children of my root CompanyName element'. Hence the list is empty.
how can I get list of all SubContainer elements.
You can use
var subContainers = doc.Root.Descendants("SubContainer");
when I got the list of SubContainer elements, how can I read read and change its content?
foreach (var subContainer in subContainers)
{
foreach (var attrContainer in subContainer.Elements("AttrContainer"))
{
var attr = attrContainer.Elements("Attr").FirstOrDefault();
if (attr != null)
{
var oldValue = attr.Attribute("type").Value;
attr.Attribute("type").Value = "something completely different";
}
}
}
This reads and changes the type on each first Attr element (assuming one exists) in all AttrContainers in all SubContainers - hopefully you can derive something meaningful out of that.
doc.Root returns the element <CompanyName>, so further selecting elements named CompanyName won't return any elements. You're effectively trying to select all <CompanyName> elements that are children of <CompanyName>.
This code will select all <SubContainer> elements no matter their depth. I'm suggesting this because your example XML has several <SubContainer> elements.
// Read all Attr elements
IEnumerable<XElement> subContainerElements = doc.Root.Descendants("SubContainer");
foreach (XElement subContainerElement in subContainerElements)
{
// Work with <SubContainer> element here
}

Swapping nodes in xmlNodeList C#

Assuming having the following xml
<test>
<step>
<var name="name1" />
<var name="name2" />
</step>
<step>
<var name="name3" />
<var name="name4" />
</step>
<step>
<var name="name5" />
<var name="name6" />
</step>
</test>
I m using XmlNodeList, seperated by "step". Is there a way to swap or replace a step directly in the xmlnodelist?
Need to make it like this:
<test>
<step>
<var name="name3" />
<var name="name4" />
</step>
<step>
<var name="name1" />
<var name="name2" />
</step>
<step>
<var name="name5" />
<var name="name6" />
</step>
</test>
You can use XDocument class instead of XMLDocument. This will swap the var nodes name3 with name6.
using System.Linq;
using System.Xml.Linq;
class Test
{
static void Main()
{
XDocument document = XDocument.Load("test.xml");
Swap("name3", "name6", document);
document.Save("test.xml");
}
static void Swap(string nameOne, string nameTwo, XDocument document)
{
var nameOneNode = document.Descendants("var").FirstOrDefault(p => p.Attribute("name").Value == nameOne);
var nameTwoNode = document.Descendants("var").FirstOrDefault(p => p.Attribute("name").Value == nameTwo);
nameOneNode.Attribute("name").Value = nameTwo;
nameTwoNode.Attribute("name").Value = nameOne;
}
}
The order of the nodes in an XML file does not necessarily have to be kept when the XML file is read. For example, if your file looks like this:
<xmlcontent>
<node value="Hello" />
<node value="World" />
</xmlcontent>
The XML read may return the nodes like this:
<xmlcontent>
<node value="World" />
<node value="Hello" />
</xmlcontent>
To apply something like an "order" to XML nodes, you need to add an attribute you can sort by, like
<xmlcontent>
<node index="1" value="Hello" />
<node index="2" value="World" />
</xmlcontent>
In that case, "swapping" two elements would come down to swapping the index values.
Finally managed to do it, here is the code:
XmlDocument xml;
XmlNodeList xmlList;
xml = new XmlDocument();
xml.Load(path);
xmlList = xml.GetElementsByTagName("step");
XmlNode refNode = xmlList[1];
XmlNode newNode = xmlList[0];
xml.DocumentElement.InsertAfter(newNode, refNode);

Categories