1

I need to create an XmlDocument partly by using old XML and partly by creating new. The problem is that the old XML contains custom namespaces and I can't seem to be able to use them as I get an XmlException. I've tried to add the namespace to many different places but I can't get over the Exception!

The Exception

System.Xml.XmlException was unhandled by user code
    Message='my' is an undeclared prefix. Line 1, position 42.
    Source=System.Xml

My Code

XmlDocument doc = new XmlDocument();
XmlSchema schema = new XmlSchema();
schema.Namespaces.Add("my", "http://foobar.com/");
doc.Schemas.Add(schema);
XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
doc.AppendChild(dec);

XmlElement root = doc.CreateElement("root");
root.SetAttribute("xmlns:my", "http://foobar.com/");
doc.AppendChild(root);

foreach (var item in GetItems())
{
    XmlElement elem = doc.CreateElement("item");
    elem.SetAttribute("id", item.id);

    // Append body to elem
    XmlElement body = doc.CreateElement("body");
    body.InnerXml = item.Body; // Here is where I get the exception

    elem.AppendChild(body);

    // Append elem to root
    root.AppendChild(elem);
}

Input from Item.Body is similar to

<aaa><bbb my:attr="55">Foo</bbb></aaa>

I expected the output to be similar to

<?xml version="1.0" encoding="utf-8"?>
<root my:attr="http://foobar.com/">
  <item id="12345">
    <body>
        <aaa>
            <bbb my:attr="55">Foo</bbb>
        </aaa>
    </body>
  </item>
</root>

I'm open to alternatives to using this method. After I create the XmlDocument I prettyprint it, validate it against a schema and then push it out for the user to see.

Joel Peltonen
  • 13,025
  • 6
  • 64
  • 100
  • I'm open to suggestions on doing this differently as well if this seems like a bad way to create XML from existing and new sources at the same time! – Joel Peltonen Nov 02 '12 at 08:40
  • What is the exception? And post (a part) of the desired XML as well. – H H Nov 02 '12 at 09:09
  • Can you use XLinq (XElement) ? Makes working with Xml and esp. namespaces a lot easier. – H H Nov 02 '12 at 09:09
  • Edited to add more details. Henk, I can use anything in .net 4 and am open to using Linq too. – Joel Peltonen Nov 02 '12 at 09:20
  • When trying with Linq to XML (like your old answer) and replacing the exception throwing line with `body.ReplaceAll(XElement.Parse(topicRevision.Body));` I get the same exception. The Parser parsing my old incoming XML clearly gets confused on my namespace but I don't know how to overcome the issue. – Joel Peltonen Nov 02 '12 at 10:10
  • You have a deep problem, the `my:` in `` simply isn't valid while reading/parsing this. Anything you can change at the source? I think including `"http://foobar.com/"` would be easier. There are no good tools/ways to deal with invalid XML. – H H Nov 02 '12 at 10:44

1 Answers1

0

The following is a workaround, best I can come up with:

 XNamespace  my = "http://foobar.com/";

 var doc = new XDocument(new XElement("root", 
                new XAttribute(XNamespace.Xmlns +  "my", my)));

 var body = new XElement("body");
 doc.Root.Add(new XElement("item", new XAttribute("id", 12345), body));

 string innerItem = @"<aaa><bbb my:attr=""55"">Foo</bbb></aaa>";       
 string itemWrap = @"<wrap xmlns:my=""http://foobar.com/"">" + innerItem + "</wrap>";

 XElement item = XElement.Parse(itemWrap);
 body.Add(item.Element("aaa"));

 Console.WriteLine(doc);
H H
  • 263,252
  • 30
  • 330
  • 514
  • Thanks, I'm happy with this workaround. I'll have a talk with the source generating side and see if we can get the deeper issue fixed! – Joel Peltonen Nov 02 '12 at 11:04