1

I am creating an XML file which starts like this:

 XNamespace xNamespace = "http://www.topografix.com/GPX/1/1";
        var trkseg = new XElement("trkseg");
        XElement GPX = new XElement(xNamespace + "gpx",
            new XAttribute("xmlns", xNamespace),
            new XAttribute("version", "1.0"),
            new XAttribute("creator", "quilkin.co.uk"),
            new XElement("trk",
                new XElement("name", RouteName()),
                trkseg
            )
        );

which produces the following:

<gpx creator="quilkin.co.uk" version="1.0" xmlns="http://www.topografix.com/GPX/1/1">
  <trk xmlns="">
    <name>Route Name</name>
    <trkseg/>
  </trk>
</gpx>

I'm puzled why the 'trk' element has an attribute 'xlmns'. The addition of this isn't a problem with most readers of GPX files, but one (very common one!) does not like it and refuses to load the file.

I could manipulate the text to remove the attribute, but why is it occuring?

quilkin
  • 874
  • 11
  • 31

1 Answers1

4

The xmlns attribute defines the namespace of the current and all descendent elements that do not have an explicit namespace in front of them. Example:

<a xmlns="x">          // = namespace x, tag a
  <b>                  // = namespace x, tag b
    <c xmlns="">       // = empty namespace, tag c
      <d>              // = empty namespace, tag d
      </d>
    </c>
  </b>
</a>         

Or, if you prefer a more real-life example:

<html xmlns="http://www.w3.org/1999/xhtml">
  <body>
    <svg xmlns="http://www.w3.org/2000/svg">
      <rect x="20" y="20" width="50" height="50" />
    </svg>
  </body>
</html>

Here, html and body are in the XHTML namepsace, whereas svg and rect are in the SVG namespace.


In your code, you create gpx with the namespace contained in xNamespace, but you create subsequent elements with an empty namespace. Thus, XML needs to "reset" the namespace to empty in trk.

If you want to get rid of the xmslns="" attribute, just make sure that all elements are in the same namespace, i.e. replace

new XElement("trk",
    new XElement("name", RouteName()),
    new XElement("trkseg"))

with

new XElement(xNamespace + "trk",
    new XElement(xNamespace + "name", RouteName()),
    new XElement(xNamespace + "trkseg"))
Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • Thank you. And of course I need to add the namespace to all the inner tags (not shown in my simple example) as well! – quilkin Jun 14 '22 at 12:37
  • But surely the empty attribute `xmlns=""` shouldn't cause an error in an XML reader? If it shouldn't, does that mean that a very well-known company's code is incorrect? – quilkin Jun 14 '22 at 12:39
  • @quilkin: Why shouldn't it cause an error? It expects the `trk` element with the GPX namespace, and instead it gets the `trk` element with an empty namespace. So, clearly, something is wrong. – Heinzi Jun 14 '22 at 12:42
  • 1
    @quilkin: In other words: `xmlns` is not just a "plain old attribute". In a way, it can be seen as part of the tag name (of the current and all descending elements). – Heinzi Jun 14 '22 at 13:09
  • OK, but I only asked this supplementary question because at least 4 or 5 common online GPX file readers don't complain - only one did. Otherwise I would have found the error two years ago when I wrote the code! – quilkin Jun 15 '22 at 18:53
  • @quilkin: My guess is that (a) they didn't understand XML namespace either and just ignored them or (b) they deliberately decided to accept "broken" XML as well, because so many of their users did not understand XML namespaces and they got tired of explaining. – Heinzi Jun 15 '22 at 20:30