Reputation: 706
I'm having trouble composing an XDocument which uses two namespaces. When I add XElements created by a different method (which refer to the exact same XNamespace instances), I get a redeclaration of the xmlns with a different prefix. It's perfectly correct XML, but is a bear for human readability.
XDocument xml = new XDocument();
XElement e_graphml = new XElement(ns_graphML + "graphml",
new XAttribute("xmlns", ns_graphML),
new XAttribute(XNamespace.Xmlns + "y", ns_yGraphML));
xml.Add(e_graphml);
XElement child = graph.ToX();
e_graphml.Add(child);
The graph object uses my globally available ns_graphML and ns_yGraphML objects, both type XNamespace. Yet the XML I get back serializes to text as:
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:y="http://www.yworks.com/xml/graphml">
<graph p3:edgedefault="directed" p3:id="fileReferences" xmlns:p3="http://graphml.graphdrawing.org/xmlns" />
</graphml>
(EDIT) I expect:
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:y="http://www.yworks.com/xml/graphml">
<graph edgedefault="directed" id="fileReferences"/>
</graphml>
(/EDIT)
The graph element should inherit the default xmlns once it is added to e_graphml, but apparently these are considered different. Note thate graph.ToX() does not add explicit namespace attributes (xmlns=...) to the returned graph XElement; the XNames in it simply refer to the namespace, like so:
XElement e_graph = new XElement(ns_graphML + "graph",
new XAttribute(ns_graphML + "edgedefault", "directed"),
new XAttribute(ns_graphML + "id", Name));
Perhaps this is a duplicate of Force XDocument to not use namespace prefix if namespace is also defined as default, but I'm creating the XDocument entirely in code, not from initial XML text.
Upvotes: 0
Views: 374
Reputation: 134491
I think this behavior is intended. Attributes without a namespace prefix isn't part of any namespace, not even the default namespace. It needed to put the attribute in that namespace but since it didn't have a prefix to use, it had to create one. I think it'll be easier to just create the document but use explicit prefixes for the namespaces, it'll come out a lot cleaner.
var e_graphml = new XElement(ns_graphML + "graphml",
new XAttribute(XNamespace.Xmlns + "g", ns_graphML),
new XAttribute(XNamespace.Xmlns + "y", ns_yGraphML)
);
This will yield xml like so:
<g:graphml xmlns:g="http://graphml.graphdrawing.org/xmlns" xmlns:y="http://www.yworks.com/xml/graphml">
<g:graph g:edgedefault="directed" g:id="fileReferences" />
</g:graphml>
If you specifically want to have it render the attributes without prefixes, remove the namespace when you generate them. Attributes typically don't need to be namespaced unless explicitly required.
var e_graph = new XElement(ns_graphML + "graph",
new XAttribute("edgedefault", "directed"),
new XAttribute("id", Name)
);
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:y="http://www.yworks.com/xml/graphml">
<graph edgedefault="directed" id="fileReferences" />
</graphml>
Upvotes: 2