次の方法で共有


System.Xml Hacking (AppendXml vs. InnerXml)

I was spending some time composing Soap Messages using System.Xml, but I found a strange behavior of System.Xml while adding nodes to an existing XmlDocument.

 

I have an empty soap envelope like this:

 

string soapEnvelope = "<s:env xmlns:s='soap'><s:body /></s:env>";

 

What I want is to add the method payload from the next information:

 

string methodName = "m";

string ns="urn:ns";

string methodBody = "<name>rido</name>";

My first attempt was a mix between AppendChild and InnerXml

 

XmlDocument doc = new XmlDocument();

doc.LoadXml(soapEnvelope);

XmlElement methodNode = doc.CreateElement(methodName, ns);

methodNode.InnerXml = methodBody;

XmlNode body = doc.GetElementsByTagName("s:body")[0];

body.AppendChild(methodNode);

However the result output was

 

<s:env xmlns:s="soap">

  <s:body>

    <m xmlns="urn:ns">

      <name xmlns="">rido</name>

    </m>

  </s:body>

</s:env>

Note the empty namespace declaration in the name element, and the bad news is that ASP.Net needs the namespace information to deserialize the request message, so I have to hack System.Xml to avoid this behavior.

 

I take a look to news://microsoft.public.dotnet.xml and I only a found a few messages talking about how to remove the attribute once the final message is composed, but I would like to avoid the empty namespace (xmlns=””) while composing the doc. After playing a little bit with the API I found the solution:

 

Instead of creating the method element with AppendChild, I’m going to manually build the whole method element in a string, and assign it to the body InnerXml property:

 

XmlDocument doc = new XmlDocument();

doc.LoadXml(soapEnvelope);

XmlNode body = doc.GetElementsByTagName("s:body")[0];

string methodXml = String.Format("<{0} xmlns='{1}'>{2}</{0}>",

      methodName, ns, methodBody);

body.InnerXml = methodXml;

 

 

Now it works…

Comments

  • Anonymous
    December 07, 2004
    I figured this out....<br><br>(doc is an XmlDocument) <br><br>XmlElement root = doc.DocumentElement;<br><br> string defaultns = string.Empty;// = &quot;urn:schemas-microsoft-com:office:spreadsheet&quot;;<br><br> defaultns = root.NamespaceURI;<br><br> XmlElement rowElem = doc.CreateElement (&quot;Row&quot; , defaultns);<br><br>This got rid of the &quot;empty namespace&quot;. What is happening is that because their is ~~already a default namespace, its putting one in for the UnIdentified (namespace) for the new XmlElement.<br><br>C# code is above.<br><br>..