linq-to-xmlxelementxattributexnamespace

Controling XElement Attribute Namespace Names


I'm in the process of building an export engine that will take our company's data and export it as XML based on the pattern provided in our database. One of the exports I need to implement must have the xsi:nil="true" attribute added to the element when the element's value is null.

I loop through each item in the export list, generate it's inner XElement objects (based on our rules), and save the .ToString() representation to the database. After all of the inner pieces are generated they are pulled from the db, parsed back into XElement objects, and added to the outer xml root. (Having it all in the database allows for pausing an export, resuming an export after server restart, etc)

I have specified the xsi namespace in the outer root, however this does not work when adding the (parsed)inner XElement.

This is a representation of how my code currently works:

//Generate inner xml
XElement innerElement = new XElement("inner");
XNamespace xsi = @"http://www.w3.org/2001/XMLSchema-instance";
XAttribute attrib = new XAttribute(xsi + "nil", "true");
innerElement.Add(attrib);

//Mock out saving XElement as string
string innerString = innerElement.ToString();
XElement innerElementParsed = XElement.Parse(innerString);

//Add innerxml to outer xml root
XNamespace outerXsi = "http://www.w3.org/2001/XMLSchema-instance";
XAttribute outerAttrib = new XAttribute(XNamespace.Xmlns + "xsi", outerXsi);
XElement outerElement = new XElement("Outer", outerAttrib);
outerElement.Add(innerElementParsed);
return outerElement.ToString();

I get the following results

<Outer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <inner p1:nil="true" xmlns:p1="http://www.w3.org/2001/XMLSchema-instance" />
</Outer>

I cannot figure out how to have it not use Expanded Names (towards the bottom of this page: http://msdn.microsoft.com/en-us/library/system.xml.linq.xnamespace.aspx)

If I were able to remove the ".ToString()" step of saving it to the database in the middle, I wouldn't have this problem because adding all of the XElement items directly resolves the namespaces correctly.

So my question is: Is there a way to control the parsing to tell it to not use the Expanded name p1 and instead use the outer XElement's namespace? OR Is there something out there that will look at the Expanded Name and see that it is the same as the root and therefore remove it?


Solution

  • What we ended up doing to resolve this was to add an "outer" XElement (with the appropriate namespaces declared) around each of the results before doing the .ToString() and saving them to the database. Then later when we pull the item's xml results out of the database and parse it back into an XElement, we look at that XElement's .Elements() property and pull that into our larger "final" XElement object instead of the parsed XElement itself.