Wrong data is entered and it turns out like this. There is XML in which there are a lot of tags, among which these 2 <name> and <description> . If the XML structure is important, then I'll try to reproduce it now.

 <name>ΠΌΠΎΠ»ΠΎΡ‡Π½ΠΎ-кислый ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚</name> <description>ΠšΠ΅Ρ„ΠΈΡ€</description> 

How to swap the contents of the tags to get it? and save the file

 <name>ΠšΠ΅Ρ„ΠΈΡ€</name> <description>ΠΌΠΎΠ»ΠΎΡ‡Π½ΠΎ-кислый ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚</description> 

Of course, I’ll try to just rename the tags, but for now I don’t know if it will affect the further processing of xml. What do you think?

  • It does not change, of course, if the processing is done correctly . - VladD

4 answers 4

You can use XPath to search for tags. For example, if there are several offer tags in xml and you need to find the one with <categoryId>64</categoryId> , then we write the following XPath: "//offer[categoryId/text()='64']"

 // #r "System.Xml.Linq" using System.Xml.Linq; using System.Xml.XPath; using System.Xml; using System.IO; class Xml { static void Update(XElement x) { foreach (var n in x.Descendants("name")) { var d = n.Parent.Element("description"); var v = n.Value; n.Value = d.Value; d.Value = v; } } static void Process(IEnumerable<string> cats, XElement file) { foreach (var cat in cats.Distinct()) { var xs = file.XPathSelectElements("//offer[categoryId/text()='" + cat + "']"); foreach(var x in xs.ToList()) Update(x); } } public static XElement ProcessFile(string cats, string file, int skipFileLines) { var xml = String.Concat(System.IO.File.ReadLines(file).Skip(skipFileLines)); var x = XElement.Parse(xml); Process(File.ReadLines(cats).ToList(), x); return x; } } 

 var root = @"C:\Temp\"; var x = Xml.ProcessFile(root+"cats.txt", root+"file.xml", 1); x.Save(root + "file.new.xml"); 

here in Xml.ProcessFile it is passed 1 - so that when loading xml, skip the line <?xml version="1.0" encoding="utf8"?> , since there is an error in it - utf8 , and there should be utf-8 .

  • Comments are not intended for extended discussion; conversation moved to chat . - Nick Volynkin ♦
 // #r "System.Xml.Linq" using System.Xml.Linq; var xml = @"<name>ΠΌΠΎΠ»ΠΎΡ‡Π½ΠΎ-кислый ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚</name> <description>ΠšΠ΅Ρ„ΠΈΡ€</description>"; var x = XElement.Parse("<r>" + xml + "</r>"); var n = x.Element("name"); var d = x.Element("description"); var s = new XElement(n.Name, d.Value) + "\n" + new XElement(d.Name, n.Value); 

Result

 <name>ΠšΠ΅Ρ„ΠΈΡ€</name> <description>ΠΌΠΎΠ»ΠΎΡ‡Π½ΠΎ-кислый ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚</description> 
  • Oh, and please, with the file upload, tell me ... like file.xml and everything is already changing in it - Andrey
  • @Andrey "with the file upload, tell me ... of type file.xml and everything is already changing in it" - but what about the file? just two lines? if not, add a precise example to the question. - Stack
  • @ Andrei and what to do with the result? write to the same file? - Stack
  • Updated the question. With the result, yes, change and save. - Andrei
  • @ Andrei added another answer. for files. - Stack

file.xml should be saved in utf-8 encoding

 <data> <item> <name>ΠΌΠΎΠ»ΠΎΡ‡Π½ΠΎ-кислый ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚</name> <description>ΠšΠ΅Ρ„ΠΈΡ€</description> </item> <item> <name>Молоко ΠΏΠΎΠ»Π΅Π·Π½ΠΎ</name> <description>Молоко</description> </item> </data> 

 // #r "System.Xml.Linq" using System.Xml.Linq; using System.Linq; var path = @"C:\Temp\"; var x = XElement.Load(path+"file.xml"); foreach(var n in x.Descendants("name")) { var d = n.Parent.Element("description"); var v = n.Value; n.Value = d.Value; d.Value = v; } x.Save(path+"file.new.xml"); MessageBox.Show("Π“ΠΎΡ‚ΠΎΠ²ΠΎ!"); 

Result

 <?xml version="1.0" encoding="utf-8"?> <data> <item> <name>ΠšΠ΅Ρ„ΠΈΡ€</name> <description>ΠΌΠΎΠ»ΠΎΡ‡Π½ΠΎ-кислый ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚</description> </item> <item> <name>Молоко</name> <description>Молоко ΠΏΠΎΠ»Π΅Π·Π½ΠΎ</description> </item> </data> 
  • Swears something on n.Value = d.Value; (To create an instance of an object with the reserved word new). There are a lot of tags <name> and <description> that would loop them all - Andrey
  • Understood why swore, it turns out on the order of the tags depends. Oh, and if it doesn't make it difficult, then saving the result to a new file, for example file.new.xml ", to check for replacements - Andrey
  • In XML, there are several tags for sequential replacement, but for some reason it does 1 replacement and exit. I do not understand. Maybe it makes sense to tie the fact that these tags are between the tags <item> </ item>? - Andrei
  • @Andrew "There are several tags in XML for consistent replacement" - throw off an example xml on pastebin.com - Stack
  • Is done. pastebin.com/TmgqDiSy - Andrei

If the content of the name longer than the content of the description , then the Update method can be replaced with the following:

 static void Update(XElement x) { Func<string, string> txt = s => System.Text.RegularExpressions.Regex.Replace(s, @"[\s\r\n]", ""); foreach (var n in x.Descendants("name")) { var d = n.Parent.Element("description"); if(txt(n.Value).Length > txt(d.Value).Length) { var v = n.Value; n.Value = d.Value; d.Value = v; } } }