<ns1:Message xmlns:ns1="http://www.domain1.com/v1" xmlns:ns2="http://
www.domain2.com/v1" xmlns:ns3="http://www.domain3.com/v1"
xmlns:ns4="http://www.domain4.com/v1" xmlns:ns5="http://
www.domain5.com/v1"><ns1:Ack ns1:messageId="1"
ns1:dateTimeSent="2009-12-31T01:30:14.0462064Z" /></ns1:Message>
As you can see, ns2 through ns5 are extraneous.
Sometimes, more than 50% of the message is just unused namespaces and
I would like to remove them after I receive the XmlDocument (cannot
change the library) and before I send the message over the wire.
Are there any Xml-related classes or methods (C#, .NET 3.5) that I can
use to parse the XmlDocument and remove the unused namespaces?
Does XmlDocument mean you have a System.Xml.XmlDocument? Or do you get
an XML document you could parse with LINQ to XML
(System.Xml.Linq.XDocument)?
One way to get rid of unused namespaces is to simply get rid of any
namespace declaration attributes, then serialize the document and the
serializer will take care of adding any namespace declarations that are
necessary to have a namespace well-formed document:
So with your above sample document the code
XDocument doc = XDocument.Load("input.xml",
LoadOptions.PreserveWhitespace);
doc.Descendants().Attributes().Where(a =>
a.IsNamespaceDeclaration).Remove();
doc.Save("output.xml", SaveOptions.DisableFormatting);
would output
<Message xmlns="http://www.domain1.com/v1"><Ack p2:messageId="1"
p2:dateTimeSent="2009-12-31T01:30:14.0462064Z"
xmlns:p2="http://www.domain1.com/v1" /></Message>
That document is semantically equivalent to the one you posted, only the
serializer has choosen to put the elements in the default namespace and
to use the prefix 'p2' for the attributes.
Does that suffice for your needs?
--
Martin Honnen --- MVP XML
http://msmvps.com/blogs/martin_honnen/
I think it will. I'll try it and get back to you. Thank you.
> Does XmlDocument mean you have a System.Xml.XmlDocument? Or do you get
> an XML document you could parse with LINQ to XML
> (System.Xml.Linq.XDocument)?
>
> One way to get rid of unused namespaces is to simply get rid of any
> namespace declaration attributes, then serialize the document and the
> serializer will take care of adding any namespace declarations that are
> necessary to have a namespace well-formed document:
>
> So with your above sample document the code
>
> XDocument doc = XDocument.Load("input.xml",
> LoadOptions.PreserveWhitespace);
> doc.Descendants().Attributes().Where(a =>
> a.IsNamespaceDeclaration).Remove();
> doc.Save("output.xml", SaveOptions.DisableFormatting);
>
> would output
>
> <Message xmlns="http://www.domain1.com/v1"><Ack p2:messageId="1"
> p2:dateTimeSent="2009-12-31T01:30:14.0462064Z"
> xmlns:p2="http://www.domain1.com/v1" /></Message>
>
> That document is semantically equivalent to the one you posted, only the
> serializer has choosen to put the elements in the default namespace and
> to use the prefix 'p2' for the attributes.
>
> Does that suffice for your needs?
I think it will. I'll try it and get back to you. Thank you.
> I think it will. I'll try it and get back to you. Thank you.
I can't get this to build with VS 2008 professional, console app,
project's target framework is .NET 3.5
...
using System.Collections;
using System.Collections.Generic;
using System.Xml.Linq;
...
XDocument doc = XDocument.Load("input.xml",
LoadOptions.PreserveWhitespace);
doc.Descendants().Attributes().Where(a =>
a.IsNamespaceDeclaration).Remove();
Error 504 (on doc.Descendants()...")
'System.Collections.Generic.IEnumerable<System.Xml.Linq.XAttribute>'
does not contain a definition for 'Where' and no extension method
'Where' accepting a first argument of type
'System.Collections.Generic.IEnumerable<System.Xml.Linq.XAttribute>'
could be found (are you missing a using directive or an assembly
reference?)
Been through the MSDN site but I keep hitting an information roadblock
at XDocument.Descendants. Not sure where to proceed from there to get
to .Attributes().Where()
What using or assembly reference might I be missing?
> I can't get this to build with VS 2008 professional, console app,
> project's target framework is .NET 3.5
>
> ...
> using System.Collections;
> using System.Collections.Generic;
> using System.Xml.Linq;
You also need
using System.Linq;
and a reference to System.Core.dll.
I ended up with a different solution, once I understood that I could
XmlSerializer.Serialize() without the XmlSerializerNamespaces()
parameter and still get semantically correct Xml.
Works great!