I have an XML Document that stores all sorts of information about users of a system. Utlimately, the nodes that I am intersted in I hae outined below.
So, there is a user that has many user contents - I have included just books as an example.
<?xml version="1.0" encoding="UTF-8"?>
<user>
<userProperties>
<alias val="userAliasOne"/>
<id val="3423423"/>
</userProperties>
<userContent>
<userBooks>
<genre>
<book>
<title>Dummy Value</title>
</book>
</genre>
</userBooks>
</userContent>
</user>
I need to somehow restructure the XML, using XmlDocument and XmlNode so that it matches the below. (userBooks to become root node but all contents of userBooks - /genre/book/title - to stay inside userContent).
<?xml version="1.0" encoding="UTF-8"?>
<userBooks>
<user>
<userProperties>
<alias val="userAliasOne"/>
<id val="3423423"/>
</userProperties>
<userContent>
<genre>
<book>
<title>Dummy Value</title>
</book>
</genre>
</userContent>
</user>
</userBooks>
I've tried selecting the single nodes and cloning them, then appending the clone to the parent and removing the child that's no longer required. It became very long and convoluted and I couldn't get it to work. There must be a more elegant solution that I am not aware of.
Any help appreciated.
Thanks.
Using XML Linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
List<XElement> userBooks = doc.Descendants("userBooks").ToList();
foreach(XElement userBook in userBooks)
{
userBook.ReplaceWith(userBook.Element("genre"));
}
}
}
}
Here's an example for adding a new root element:
using System;
using System.Xml;
class Test
{
static void Main()
{
XmlDocument doc = new XmlDocument();
doc.Load("test.xml");
var originalRoot = doc.DocumentElement;
doc.RemoveChild(originalRoot);
var newRoot = doc.CreateElement("userBooks");
doc.AppendChild(newRoot);
newRoot.AppendChild(originalRoot);
doc.Save(Console.Out);
}
}
Try using the same approach for "removing" the userBooks element in the original - remove the element from its parent, but then add all the child nodes (of userBooks) as new child nodes of the original parent of userBooks.
Related
I've searched Stackoverflow on this question, as well as other forums but no one seems to be making this the way I'm making.
By this I mean, in my code, instead of using XMLNode, I'm using XMLElement.
So, without further ado, my intention is to save in an already existing XML Document, a new Element is a child of other existing Elements besides the root.
This is an example on my XML File:
<ROOT>
<NOT_THIS_ONE>
</NOT_THIS_ONE>
<THIS_ONE>
</THIS_ONE>
</ROOT>
So, this is my code:
//XML File
TextAsset repository = Resources.Load("Repository") as TextAsset;
//Create XML Reference
XmlDocument xmlDocument = new XmlDocument();
//Load XML File into XML Reference
xmlDocument.LoadXml(repository.text);
//Root Node
XmlNode statsNode = GetRootNode();
//Get History Node
XmlNode thisOneNode = statsNode.ChildNodes.Item(1);
The GetRootNode() function is this:
//Create Xml Reference
XmlDocument xmlData = new XmlDocument();
//Load Xml File into Xml Reference
xmlData.LoadXml(repository.text);
//Get Root Node
return xmlData.ChildNodes.Item(1);
The thisOneNode gets the <THIS_ONE> Element as a Node (at least that's what I think it does).
Later on, I do this:
XmlElement childOfThisOne = xmlDocument.CreateElement("CHILD");
XmlElement pointsSession = xmlDocument.CreateElement("POINTS");
pointsSession.InnerText = points.ToString();
childOfThisOne.AppendChild(pointsSession);
thisOneNode.AppendChild(childOfThisOne);
xmlDocument.Save("Assets/Resources/GamePoints.xml");
And my intention with this would be something like:
<ROOT>
<NOT_THIS_ONE>
</NOT_THIS_ONE>
<THIS_ONE>
<CHILD>
<POINTS>102</POINTS>
</CHILD>
</THIS_ONE>
</ROOT>
But I get the error in the title: "ArgumentException: The node to be inserted is from a different document context."
And the line in question is this: thisOneNode.AppendChild(childOfThisOne);
Now, where I've searched and the articles I found, people were using XmlNode and even used an xmlDocument.ImportNode(); I tried that too and the same error occurred. Now, I don't how to fix this and I'm requesting your help on this one.
Thank you for your time and happy holidays!
Using Xml Linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string xml =
#"<ROOT>
<NOT_THIS_ONE>
</NOT_THIS_ONE>
<THIS_ONE>
</THIS_ONE>
</ROOT>";
XDocument doc = XDocument.Parse(xml);
XElement thisOne = doc.Descendants("THIS_ONE").FirstOrDefault();
thisOne.Add(new XElement("CHILD", new XElement("POINTS", 102)));
doc.Save("Assets/Resources/GamePoints.xml");
}
}
}
i want to read xml file but due to Document node attribute it did not read file.
Code C#:
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(HttpContext.Server.MapPath("~/Content/Images/MMS-CREATE-ALLA-ALLAH2H1-23102018-000170-INP.xml"));
XmlNode settings = xmldoc.SelectSingleNode("Document[#xmlns='urn:iso:std:iso:20022:tech:xsd:pain.009.001.01']/MndtInitnReq/GrpHdr");
stu.BranchName = settings.SelectSingleNode("MsgId").InnerText;
XML FIle:
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.009.001.01">
<MndtInitnReq>
<GrpHdr>
<MsgId>10005226074</MsgId>
<CreDtTm>2018-10-23T15:20:56</CreDtTm>
</GrpHdr>
</MndtInitnReq>
</Document>
You have a namespace that must be used to get the data. Try Xml Linq :
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication75
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XNamespace ns = doc.Root.GetDefaultNamespace();
string msgId = (string)doc.Descendants(ns + "MsgId").FirstOrDefault();
XElement xCreDtTm = doc.Descendants(ns + "CreDtTm").FirstOrDefault();
//will give 1/1/01 when null
DateTime CreDtTm = xCreDtTm == null ? new DateTime() : (DateTime)xCreDtTm;
}
}
}
I don't think loading this xml should be a problem. I verified that by loading the xml you posted in an XmlDocument object.
However I think, your xpath to get "settings" node should have xml namespace in all tags after Document.
So the xpath should be "/[local-name()='Document' and namespace-uri()='urn:iso:std:iso:20022:tech:xsd:pain.009.001.01']/[local-name()='MndtInitnReq' and namespace-uri()='urn:iso:std:iso:20022:tech:xsd:pain.009.001.01']/*[local-name()='GrpHdr' and namespace-uri()='urn:iso:std:iso:20022:tech:xsd:pain.009.001.01']"
I have XML code that looks similar to this:
<BookStore xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Book>
<bookGenre>Fantasy</bookGenre>
<bookTitle>A Storm of Swords</bookTitle>
<authorInformation>
<authorId>12345</authorId>
<authorName>
<firstName>George</firstName>
<middleInitial>R.R.</middleInitial>
<lastName>Martin</lastName>
</authorName>
</authorInformation>
</Book>
<customer>
<customerData />
</customer>
</BookStore>
The <customer>node may or may not have child nodes, depending on user input.
I am trying to use XmlDocument.SelectNodes and XPath navigation to select <BookStore>, <customer>, and any nodes contained within <customer>.
I have been looking around and reading about XPath and .SelectNodes for a few hours but still don't seem to fully understand how they work. Would anyone have an explanation as to how to use them or how I could use them in my situation? If there are other ways to go about solving my problem I'm open to those too! (I am using C#)
EDIT: here's what I tried based on the stuff I read
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlStr);
XmlNode root = doc.DocumentElement;
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("xsd", "http://www.w3.org/2001/XMLSchema");
nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
XmlNodeList nodeList = root.SelectNodes("descendant::customer:child::Node");
doc.Save(Console.Out);
Try xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication62
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement customer = doc.Descendants("customer").FirstOrDefault();
Boolean children = customer.HasElements;
}
}
}
Hello and today I want to find out how I can read an xml file in the following way, I have not been able to find ANYTHING like this or anythig simulaur to how I want to do this that works. I have an xml file with the following content format that has been disabled below this.
<smallusers>
<user id="1">
<name>John</name>
<motto>I am john, who are you?</motto>
</user>
<user id="2">
<name>Peter</name>
<motto>Hello everyone!</motto>
</user>
</smallusers>
<bigusers>
<user id="3">
<name>Barry</name>
<motto>Earth is awesome</motto>
</user>
</bigusers>
How can I put that into 2 string lists in csharp
Load it as a text file into a string or StringBuilder.
prefix it with <xml> and end it with </xml>
then use XmlDocument to load your xml
XML can have only one root tag. You input has more than one root. So you have to wrap your XML in a root like code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.txt";
static void Main(string[] args)
{
string input = File.ReadAllText(FILENAME);
input = string.Format("<Root>{0}</Root>", input);
XElement root = XElement.Parse(input);
}
}
}
How can I add a process instruction to ~50 xml files?
<?xml-stylesheet type="text/xsl" href="Sample.xsl"?>
If I append the node, it is added to the end of the file but it needs to be first.
I would use LINQ to XML:
using System;
using System.Xml.Linq;
public class Test
{
static void Main()
{
XDocument doc = XDocument.Load("test.xml");
var proc = new XProcessingInstruction
("xml-stylesheet", "type=\"text/xsl\" href=\"Sample.xsl\"");
doc.Root.AddBeforeSelf(proc);
doc.Save("test2.xml");
}
}