0

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.

Community
  • 1
  • 1
Bob Peterson
  • 636
  • 7
  • 16

1 Answers1

1

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>
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
  • See also: http://stackoverflow.com/questions/3312390/xml-default-namespaces-for-unqualified-attribute-names – Jeff Mercado Aug 19 '16 at 21:34
  • Not as desirable as no prefix, but it'll do. What I get now is exactly what you say. – Bob Peterson Aug 19 '16 at 22:19
  • 1
    If you just want the prefix to not be added to the attributes, you'll just have to remove the attributes from that namespace. It should give you exactly as you wanted. – Jeff Mercado Aug 19 '16 at 22:35