Better way to convert a string to XmlNode in C# - c#

I wanted to convert a string (which obviously is an xml) to an XmlNode in C#.While searching the net I got this code.I would like to know whether this is a good way to convert a string to XmlNode? I have to preform this conversion within a loop, so does it cause any performace issues?
XmlTextReader textReader = new XmlTextReader(new StringReader(xmlContent));
XmlDocument myXmlDocument = new XmlDocument();
XmlNode newNode = myXmlDocument.ReadNode(textReader);
Please reply,
Thanks
Alex

should be straight-forward:
string xmlContent = "<foo></foo>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlContent);
XmlNode newNode = doc.DocumentElement;
or with LINQ if that's an option:
XElement newNode = XDocument.Parse(xmlContent).Root;

The accepted answer works only for single element. XmlNode can have multiple elements like string xmlContent = "<foo></foo><bar></bar>"; (Exception: "There are multiple root elements");
To load multiple elements use this:
string xmlContent = "<foo></foo><bar></bar>";
XmlDocument doc = new XmlDocument();
doc.LoadXml("<singleroot>"+xmlContent+"</singleroot>");
XmlNode newNode = doc.SelectSingleNode("/singleroot");

XmlDocument Doc = new XmlDocument();
Doc.LoadXml(xml);

Related

Insert node in xml document using c#

I was trying to insert an XML node in XML document at a specific position.
This is my xml:
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<readContract xmlns="http://implementation.company.schema.reference">
<ContactNumbers>10158</ContactNumbers>
<productGroups>0085</productGroups>
<indicationBalanceInfo>false</indicationBalanceInfo>
<indicationBlocked>true</indicationBlocked>
</readContract>
</Body>
</Envelope>
And am trying to insert another tag <productGroups>0093</productGroups> below to the tag <productGroups>0085</productGroups>
Expecting like the below:
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<readContract xmlns="http://implementation.company.schema.reference">
<ContactNumbers>10158</ContactNumbers>
<productGroups>0085</productGroups>
<productGroups>0093</productGroups>
<indicationBalanceInfo>false</indicationBalanceInfo>
<indicationBlocked>true</indicationBlocked>
</readContract>
</Body>
</Envelope>
Used the below C# code to achieve it.
XmlDocument doc = new XmlDocument();
string inputxml = this.StServiceCallActivity5.InputEnvelope.InnerXml.ToString();
//Here inputxml contains whole xml document.
string addxml = "<productGroups>0093</productGroups>";
doc.LoadXml(inputxml);
XmlDocumentFragment xmlDocFrag = doc.CreateDocumentFragment();
xmlDocFrag.InnerXml = addxml;
XmlElement parentEle = doc.DocumentElement;
parentEle.AppendChild(xmlDocFrag);
And it returns value like
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<readContract xmlns="http://implementation.company.schema.reference">
<ContactNumbers>10158</ContactNumbers>
<productGroups>0085</productGroups>
<productGroups>0093</productGroups>
<indicationBalanceInfo>false</indicationBalanceInfo>
<indicationBlocked>true</indicationBlocked>
</readContract>
</Body>
<productGroups xmlns="">0093</productGroups>
</Envelope>
Am a newbie to C# code, kindly help me to get the XML doc as expected.
your help is much appreciated.
When you do this:
XmlElement parentEle = doc.DocumentElement;
parentEle.AppendChild(xmlDocFrag);
You're appending the node to the root of the document. You probably wanted to select the actual readContract node that the item is supposed to be appended into. As an example:
XmlNode newNode = doc.CreateNode(XmlNodeType.Element, "productGroup", "");
newNode.InnerText = "something";
XmlNode readContractNode = doc["Envelope"]["Body"]["readContract"];
XmlElement groups = readContractNode["productGroups"];
readContractNode.InsertAfter(newNode, groups);
Of course you'd probably want to handle the case where there are already multiple child productGroup elements, but the idea is the same.
Looks like namespaces are causing the problem. This worked for me:
XmlDocument doc = new XmlDocument();
doc.LoadXml(File.ReadAllText("XMLFile1.xml"));
XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("ns1", "http://schemas.xmlsoap.org/soap/envelope/");
ns.AddNamespace("ns2", "http://implementation.company.schema.reference");
var rootNode = doc.SelectSingleNode("//ns1:Envelope", ns);
var readContractNode = rootNode.FirstChild.FirstChild;
var newNode = doc.CreateNode(XmlNodeType.Element, "productGroups", "http://implementation.company.schema.reference");
newNode.InnerText = "0093";
readContractNode.InsertAfter(newNode, readContractNode.SelectSingleNode("//ns2:productGroups", ns));
Or if you don't fancy namespaces like I me, you can try a bit more "brute-forcy" approach:
XmlDocument doc = new XmlDocument();
doc.LoadXml(File.ReadAllText("XMLFile1.xml"));
var newNode = doc.CreateNode(XmlNodeType.Element, "productGroups", "http://implementation.company.schema.reference");
newNode.InnerText = "0093";
doc.FirstChild.FirstChild.FirstChild.InsertAfter(newNode, doc.FirstChild.FirstChild.FirstChild.FirstChild.NextSibling);
It can be optimized but I think it helps to make the point that root cause is the different namespaces in the document.
You may want to use XmlNode.InsertAfter Method.
public virtual XmlNode InsertAfter(
XmlNode newChild,
XmlNode refChild
)
Where
newChild = The XmlNode to insert
and
refChild = The XmlNode that is the reference node. The newNode is placed after the refNode
Please check this link for information.
And check this link with answer on SO.
P.S.
Always check other answers before posting new question.

parse xml that contain colon

I have this XML text:
<test:solution xmlns:test="http://www.test.com/">
<script/>
<test:question>
<test:param name="name1">value 1</test:param>
<test:param name="name2"> value 2</test:param>
</test:question>
</test:solution>
when I run my application that contains those lines:
XmlDocument doc = new XmlDocument();
doc.Load(xmlUrl);
XmlNode testQuestions = doc.SelectSingleNode("/test:solution/test:question");
//XmlNodeList testParamNodeList = testQuestions.SelectNodes("test:param");
It give an error, I know that the error come from the colons, but I don't know how to resolve it.
Thanks for help
try this:
XmlDocument doc = new XmlDocument();
doc.Load(PATH);
XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("test", "http://www.test.com/");
XmlNode node = doc.SelectSingleNode("//test:solution//test:question", ns);

How to Select XML Nodes with XML Namespaces with C#

I have to analyze a XML doc with special namespace using C#, and I get some idea from this post. But my code fail to get the expected XML node, because the XML structure is very special...
There is a namespace in root node in XML
<MDOC xmlns="urn:schemas-microsoft-com/PSS/PSS_Survey01">
Here is my code to get this root node
XmlDocument doc = new XmlDocument();
doc.Load(path);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("urn", "schemas-microsoft-com/PSS/PSS_Survey01");
XmlNode root = doc.SelectSingleNode("MDOC", nsmgr);
Help me!
I am not sure what is special about your XML structure.
I would write the code little differently
string xmlNamespace = String.Empty;
XmlNamespaceManager nsmgr;
XmlNodeList nodeInfo = FABRequestXML.GetElementsByTagName("RootNodeName");
xmlNamespace = Convert.ToString(nodeInfo[0].Attributes["xmlns"].Value);
nsmgr = new XmlNamespaceManager(MyXml.NameTable);
nsmgr.AddNamespace("AB", xmlNamespace);
XmlNode myNode = MyXml.DocumentElement.SelectSingleNode("AB:NodeName", nsmgr);
Hope that helps

Parsing XML in C# from stream

I've tried several methods, from Linq to loading the data to an XML document, but i can't seem to be able to return the result that i need.
here's the example XML:
<serv:message xmlns:serv="http://www.webex.com/schemas/2002/06/service" xmlns:com="http://www.webex.com/schemas/2002/06/common" xmlns:event="http://www.webex.com/schemas/2002/06/service/event"><serv:header><serv:response><serv:result>SUCCESS</serv:result><serv:gsbStatus>PRIMARY</serv:gsbStatus></serv:response></serv:header><serv:body><serv:bodyContent xsi:type="event:createEventResponse" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><event:sessionKey>11111111</event:sessionKey><event:guestToken>111111111111111111111</event:guestToken></serv:bodyContent></serv:body></serv:message>
And, here's what i've tried to do:
StreamReader reader = new StreamReader(dataStream);
XmlDocument doc = new XmlDocument();
doc.LoadXml(reader.ReadToEnd());
XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
XmlNamespaceManager ns2 = new XmlNamespaceManager(doc.NameTable);
XmlNamespaceManager ns3 = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("serv", "http://www.webex.com/schemas/2002/06/service");
ns2.AddNamespace("com", "http://www.webex.com/schemas/2002/06/common");
ns3.AddNamespace("event", "http://www.webex.com/schemas/2002/06/service/event");
XmlNode node = doc.SelectSingleNode("result",ns);
Yet, for some reason i cannot ever seem to return the actual result, which should be either 'SUCCESS' or 'FAILURE' based on the actual xml above.
How can i do this?
your xpath query is not correct.
try this one :
XmlNode node = doc.SelectSingleNode("//serv:result",ns);
or
XmlNode node = doc.SelectSingleNode("serv:message/serv:header/serv:response/serv:result",ns);
This works:
XDocument doc = XDocument.Load(#"test.xml");
XNamespace serv = "http://www.webex.com/schemas/2002/06/service";
var result = doc.Descendants(serv + "result").First().Value;

Wrap XmlNode with tags - C#

I have the following xml:
<span>sometext</span>
and I want to wrap this XmlNode with another tag:
<p><span>sometext</span></p>
How can i achieve this. For parsing i use XmlDocument (C#).
The above "best answer" works if you don't care that the new "p" node ends up at the end of the parent. To replace it where it is, use:
string xml = "<span>sometext</span>";
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(xml);
// If you have XmlNode already, you can start from this point
XmlNode node = xDoc.DocumentElement;
XmlElement clone = node.Clone();
XmlNode parent = node.ParentNode;
XmlElement xElement = xDoc.CreateElement("p");
xElement.AppendChild(clone);
parent.ReplaceChild(xElement, node);
you can try something like this.
string xml = "<span>sometext</span>";
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(xml);
// If you have XmlNode already, you can start from this point
XmlNode node = xDoc.DocumentElement;
XmlNode parent = node.ParentNode;
XmlElement xElement = xDoc.CreateElement("p");
parent.RemoveChild(node);
xElement.AppendChild(node);
parent.AppendChild(xElement);
You must use the CreateNode(XmlNodeType.Element, "p", "") of XmlDocument.
Then append the old node to the new one with the AppendChild method

Categories