Search code examples
c#linqxelement

Inserting "raw" XML string into a XElement


I'm trying to load a node (in string format) into a XElement. Although this should be easy enough i'm finding some problems:

  • The node I'm trying to load contains namespace references in some sub-nodes
  • When I try to use XElement.Load() or Xelement.Parse() I get the expected not defined namespace error

I know the solution is to create a surrounding node with the namespace definitions and then load the whole thing, but I was wondering if there is a more elegant solution that doesn't involve string operations.

Here's my failed attempt :(

I have a collection of namespace attributes:

private readonly List<XAttribute> _namespaces;

This is already populated and contains all the necesary namespaces. So, to embed my XML string into another node I was doing this:

var temp = new XElement("root", (from ns in _namespaces select ns), MyXMLString);

But as I expected as well, the content of MyXMLString gets escaped and becomes a text node. The result I get is something like:

<root xmlns:mynamespace="http://mynamespace.com">&lt;mynamespace:node&gt;node text&lt;/node&gt;</root>

And the result I'm looking for is:

<root xmlns:mynamespace="http://mynamespace.com">
<mynamespace:node>node text</node>
</root>

Is there a neat way to do this?

Thanks in advance


Solution

  • Presumably your XML text is actually well formed (note the namespace qualifier on the closing tag):

    var xml = "<mynamespace:node>node text</mynamespace:node>";
    

    In which case you can use this to manually specify the namespaces:

    var mngr = new XmlNamespaceManager( new NameTable() );
    mngr.AddNamespace( "mynamespace", "urn:ignore" ); // or proper URL
    var parserContext = new XmlParserContext(null, mngr, null, XmlSpace.None, null);
    

    Now read and load:

    var txtReader = new XmlTextReader( xml, XmlNodeType.Element, parserContext );
    var ele = XElement.Load( txtReader );
    

    Works as expected. And you don't need a wrapper 'root' node. Now this can be inserted into any as an XElement anywhere.