System.InvalidOperationException: This document already has a 'DocumentElement' node - asp.net

I have a trouble on appending new node to xmldocument (created in the memory). I have select the root node with the XmlDocument.SelectSingleNode() method, it work sometimes and in the other time it will give me "System.InvalidOperationException: This document already has a 'DocumentElement' node." error. More information, this xml document is multi level xml document.
By the way, when i try it with unit test it work fine (always), when i implement it in ASP.NET 3.5, it become weird, work sometimes and fail sometimes. Any idea, why this can help? All advise and suggestion are welcome.
Thanks.

You can select the root node of the XmlDocument using the Property "DocumentElement". Or i think you can use the Property "FirstChild" (untested).
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
XmlElement rootNode = doc.DocumentElement;

This worked for me.
xmlOriginFile = New XmlDocument()
xmlTargetFile = New XmlDocument()
xmlOriginFile.Load(readFile) //readFile is a string that hold path to xml document
xmlTargetFile.Load(writeFile) //writeFile is a string that hold path to xml document
Dim fileNav As XPathNavigator = xmlOriginFile.CreateNavigator()
Dim fileItr As XPathNodeIterator = fileNav.Select("//data")
Dim addToDestNodes As List(Of XmlNode) = New List(Of XmlNode)
While (fileItr.MoveNext())
Dim addNode As XmlNode = CType(fileItr.Current, IHasXmlNode).GetNode()
addToDestNodes.Add(addNode)
End While //loop thru nodes
If addToDestNodes.Count > 0 Then
For Each addedNode As XmlNode In addToDestNodes
Dim addTargetNode As XmlNode = xmlTargetFile.ImportNode(addedNode, True)
xmlTargetFile.DocumentElement.AppendChild(addTargetNode)
Next
End If
xmlTargetFile.Save(xmlTarget) //xmlTarget is a string that hold path to xml document

XML has a root element and you have to add new element within this root element.
XmlElement eleParent = docDestn.CreateElement("EleParent");
XmlElement eleChild = docDestn.CreateElement("Item");
eleParent.AppendChild(eleChild);
XMLNode rootNode= xmlDoc.SelectSingleNode("RootEle");
rootNode.AppendChild(eleParent);
Plps. refer the link for detail: http://navinpandit.blogspot.in/2016/12/exception-this-document-already-has.html

Related

How to select XML node with different XML namespace?

I have a XML document which looks like :
<stReq xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<EvalRes>
<RenDtSrc xmlns="http://fakeurl.com/somthing/facade/params">
<ContentType>application/pdf</ContentType>
<DocumentName>Name</DocumentName>
<Content>Doc Content</Content>
</RenDtSrc>
</EvalRes>
</stReq>
From a asp.net application, I am trying to check if a node <RenDtSrc> exists in a document or not. Following is the code I am using to read XML file and node element
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("D:\\Test\\Doc1.xml");
XmlNodeList nodeList = xmlDoc.DocumentElement.SelectNodes("/stReq/EvalRes/RenDtSrc");
Count of nodeList returns zero even though there are child nodes inside it.
I think its something to do with namespace manager but I can't figure it out. Any help would be appreciated.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("D:\\Test\\Doc1.xml");
var nsm = new XmlNamespaceManager(xmlDoc.NameTable);
nsm.AddNamespace("s", "http://fakeurl.com/somthing/facade/params");
XmlNodeList nodeList = xmlDoc.SelectNodes("//s:RenDtSrc", nsm);
XmlNodeList nodeList = xmlDoc.DocumentElement.SelectNodes("//stReq/EvalRes/node()/*");
Output:
Node [0] = {Element, Name="ContentType"}
Node [1] = {Element, Name="DocumentName"}
Node [2] = {Element, Name="Content"}

create Xml Document from Node

Trying to create a new xml document from an existing xml node that is passed into a method. This with VB.NET. How to do ?
Private Shared Sub WriteChanges(parentNode As XmlNode, nodeName As String, m As Model.ModelBaseWithTracking)
Dim xml As New XmlDocument()
If parentNode.Name = "#document" Then
'Need code here
End If
End Sub
This is simple. You can create nodes in the XML document as following:
Private Shared Sub WriteChanges(parentNode As XmlNode, nodeName As String, m As Model.ModelBaseWithTracking)
Dim xml As New XmlDocument()
If parentNode.Name = "#document" Then
//To create root elemet
Dim root As XmlElement = xml.CreateElement("document")
xml.AppendChild(root)
//To add child node to root element
Dim child As XmlElement = xml.CreateElement("document1")
root.AppendChild(child)
child.SetAttribute("id", "1")
//Add more nodes same as shown above..
End If
End Sub

Converting string to XML node in VB.NET

I've an XML string in database column like this
<trueFalseQuestion id="585" status="correct" maxPoints="10"
maxAttempts="1"
awardedPoints="10"
usedAttempts="1"
xmlns="http://www.ispringsolutions.com/ispring/quizbuilder/quizresults">
<direction>You have NO control over how you treat customers.</direction>
<answers correctAnswerIndex="1" userAnswerIndex="1">
<answer>True</answer>
<answer>False</answer>
</answers>
</trueFalseQuestion>
But I need to do XML operations on this string like select its name, attributes values,inner text etc. How can I make this possible from this string
EDIT
Im sharing the code snippet I tried, but not working
Dim myXML As String
Dim gDt As New DataTable
gDt.Columns.Add("id")
gDt.Columns.Add("questionid")
gDt.Columns.Add("serial")
gDt.Columns.Add("direction")
Dim dr As DataRow
myXML ='<my above shared XML>'
Dim xmlDoc As New XmlDocument
xmlDoc.LoadXml(myXML)
dr = gDt.NewRow
dr("serial") = 1
dr("id") = xmlDoc.Attributes("id").Value
dr("direction") = xmlDoc("direction").InnerText
gDt.Rows.Add(dr)
But thats not working at all as I wish
There are many ways to parse XML in .NET, such as using one of the serialization classes or the XmlReader class, but the two most popular options would be to parse it with either XElement or XmlDocument. For instance:
Dim input As String = "<trueFalseQuestion id=""585"" status=""correct"" maxPoints=""10"" maxAttempts=""1"" awardedPoints=""10"" usedAttempts=""1"" xmlns=""http://www.ispringsolutions.com/ispring/quizbuilder/quizresults""><direction>You have NO control over how you treat customers.</direction><answers correctAnswerIndex=""1"" userAnswerIndex=""1""><answer>True</answer><answer>False</answer></answers></trueFalseQuestion>"
Dim element As XElement = XElement.Parse(input)
Dim id As String = element.#id
Or:
Dim input As String = "<trueFalseQuestion id=""585"" status=""correct"" maxPoints=""10"" maxAttempts=""1"" awardedPoints=""10"" usedAttempts=""1"" xmlns=""http://www.ispringsolutions.com/ispring/quizbuilder/quizresults""><direction>You have NO control over how you treat customers.</direction><answers correctAnswerIndex=""1"" userAnswerIndex=""1""><answer>True</answer><answer>False</answer></answers></trueFalseQuestion>"
Dim doc As New XmlDocument()
doc.LoadXml(input)
Dim nsmgr As New XmlNamespaceManager(doc.NameTable)
nsmgr.AddNamespace("q", "http://www.ispringsolutions.com/ispring/quizbuilder/quizresults")
Dim id As String = doc.SelectSingleNode("/q:trueFalseQuestion/#id", nsmgr).InnerText
Based on your updated question, it looks like the trouble you were having is that you weren't properly specifying the namespace. If you use XElement, it's much more forgiving (i.e. loose), but when you use XPath to select nodes in an XmlDocument, you need to specify every namespace, even when it's the default namespace on the top-level element of the document.

adding new child nodes to XML on each function call

I have an XML file and I have a function to which this XML is passed as string. I have loaded this string in Xmldocument and I need to insert few children nodes under one node. This function returns the modified XML string. I want that whenever this function is called, new child nodes are added, currently, It adds child nodes once.
Do I need to overwrite the XML file ? If so, How can I replace the node with new node ( with new child nodes added) so that It has child nodes added before the function is called again ?
My code looks something like this:
Dim doc As New XmlDocument
doc.LoadXml(applicationXml)
Dim parentNode As XmlNode = doc.GetElementsByTagName("prList").Item(0)
Dim newElement As XmlNode = doc.CreateNode(XmlNodeType.Element, "gate.util.persistence.LanguageAnalyserPersistence", Nothing)
Dim runtimeParamsElement As XmlNode = doc.CreateNode(XmlNodeType.Element, "runtimeParams", Nothing)
Dim xa As XmlAttribute = doc.CreateAttribute("class")
xa.Value = "gate.util.persistence.MapPersistence"
runtimeParamsElement.Attributes.Append(xa)
localMapElement = doc.CreateNode(XmlNodeType.Element, "localMap", Nothing)
featuresElement.AppendChild(localMapElement)
newElement.AppendChild(featuresElement)
Return doc.InnerXml
You are not showing enough code to determine the exact problem. Which node are you trying to replace? Where did featuresElement come from? Here are a few answers:
Yes you need to replace the whole file using the new document.
You don't need to replace the node with a new node. Just pass the target node to your function. The function should call appendChild() on the parent node to add a child.
When you write the document to file, example, it will have the new nodes.

Serialize Linq objects not working

Using the following code:
Private Sub MakeMeSomeXmlBeforeRyanGetsAngry()
Dim db As New MyDBDataContext
Dim customer = From c In db.Customers Select c
Dim dcs As New DataContractSerializer(GetType(Customer))
Dim sb As StringBuilder = New StringBuilder
Dim writer As XmlWriter = XmlWriter.Create(sb)
dcs.WriteObject(writer, customer)
Dim xml As String = sb.ToString
Response.Write(xml)
End Sub
I am attempting to serialize my linq collection of customers. But it keeps throwing
Type 'System.Data.Linq.DataQuery`1[MyDB.Customer]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. See the Microsoft .NET Framework documentation for other supported types.
My issue is that I have already marked the dbml Serialization Mode to UniDirectional and when I check the dbml codebehind all of the DataContract()> and DataMember()> elements are there.
I am not sure how to proceed. I have tried adding various dataloadoptions and setting deferredloading to false, but no luck.
Ideas?
This is working for me with Serialization Mode property of .dbml set to UniDirectional:
Public Shared Function CreateXml(Of T)(ByVal item As T) As String
Dim result As String = ""
Dim memoryStream As New IO.MemoryStream()
Dim serializer As New DataContractSerializer(GetType(T))
serializer.WriteObject(memoryStream, item)
memoryStream.Position = 0
Using reader As New StreamReader(memoryStream)
result = reader.ReadToEnd()
End Using
memoryStream.Close()
Return result
End Function
Dim db As New SerializerDataContext()
Dim questions = db.Questions.ToList()
Dim xmlFileName As String = "D:\\xml_test.xml"
If My.Computer.FileSystem.FileExists(xmlFileName) Then My.Computer.FileSystem.DeleteFile(xmlFileName)
Dim xml As String = XmlHelper.CreateXml(Of List(Of Question))(questions)
My.Computer.FileSystem.WriteAllText(xmlFileName, xml, True)
I think the problem arises because LINQ queries are processed only on demand, and are not serializable. Try to serialize a serializable data type resulting from your LINQ query (array, list, a single item, etc.)
dcs.WriteObject(writer, customer.ToArray)
(I assume you only need to serialize the results of the query, and not the query itself)

Resources