Nickon
Nickon

Reputation: 10146

XmlWriter makes not correct namespaces

I have a problem. I wrote a program that converts some large amount of data into VML-GML format. The problem is I need to use XmlWriter... Now I have a problem with my method below:

private void StartDocument()
{
    _writer.WriteStartDocument();
    _writer.WriteStartElement("osgb", "FeatureCollection", "osgb");
    _writer.WriteAttributeString("osgb", "xmlns", "http://namespaces.ordnancesurvey.co.uk/cmd/local/v1.1");
    _writer.WriteAttributeString("gml", "xmlns", "http://www.opengis.net/gml");
    _writer.WriteAttributeString("xsi", "xmlns", "http://www.w3.org/2001/XMLSchema-instance");
    _writer.WriteAttributeString("schemaLocation", "xsi",
                                 "http://namespaces.ordnancesurvey.co.uk/cmd/local/v1.1 http://www.ordnancesurvey.co.uk/oswebsite/xml/cmdschema/local/V1.1/CMDFeatures.xsd");
    _writer.WriteAttributeString("fid", ""); // TODO: set fid here

    _writer.WriteStartElement("gml", "description", "gml");
    _writer.WriteValue("Ordnance Survey, (c) Crown Copyright. All rights reserved, 2011-03-02");
    _writer.WriteEndElement(); // description

    _writer.WriteElementString("osgb", "creationDate", "osgb", DateTime.Today.ToString("yyyy-MM-dd"));
}

How to write in namespaces correctly? I did this in that way and the output is:

<?xml version="1.0" encoding="utf-8"?>
<osgb:FeatureCollection p1:osgb="http://namespaces.ordnancesurvey.co.uk/cmd/local/v1.1" 
p1:gml="http://www.opengis.net/gml"
p1:xsi="http://www.w3.org/2001/XMLSchema-instance" 
p2:schemaLocation="http://namespaces.ordnancesurvey.co.uk/cmd/local/v1.1 http://www.ordnancesurvey.co.uk/oswebsite/xml/cmdschema/local/V1.1/CMDFeatures.xsd"
fid="" xmlns:p2="xsi" xmlns:p1="xmlns" xmlns:osgb="osgb">

And this is what I need:

<osgb:FeatureCollection xmlns:osgb="http://namespaces.ordnancesurvey.co.uk/cmd/local/v1.1"
xmlns:gml="http://www.opengis.net/gml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://namespaces.ordnancesurvey.co.uk/cmd/local/v1.1 http://www.ordnancesurvey.co.uk/oswebsite/xml/cmdschema/local/V1.1/CMDFeatures.xsd"
fid="">

Why is that stupid XmlWriter creating such things like p1, p2, etc.?

Btw. I tried to open my output file in the program that uses those VML-GML files and it told me that the file is in a bad format. When I manually changed namespaces into the correct ones, everything was great.

How to correct it? Thanks in advance!

Upvotes: 1

Views: 4039

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1499790

Why is that stupid XmlWriter creating such things like p1, p2, etc.?

You've got your attribute values the wrong way round, and you also need to specify another argument:

This:

_writer.WriteAttributeString("gml", "xmlns", "http://www.opengis.net/gml");

should be this:

_writer.WriteAttributeString("xmlns", "gml", null, "http://www.opengis.net/gml");

Additionally, your element writing code is incorrect. You're specifying the prefix when you should be specifying the namespace URI.

I believe this does what you need:

_writer.WriteStartDocument();
// The first argument here isn't really needed, but is changes whether a
// prefix is used or not
_writer.WriteStartElement("osgb", "FeatureCollection", "http://namespaces.ordnancesurvey.co.uk/cmd/local/v1.1");
_writer.WriteAttributeString("xmlns", "osgb", null, "http://namespaces.ordnancesurvey.co.uk/cmd/local/v1.1");
_writer.WriteAttributeString("xmlns", "gml", null, "http://www.opengis.net/gml");
_writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
_writer.WriteAttributeString("schemaLocation", "http://www.w3.org/2001/XMLSchema-instance",
                             "http://namespaces.ordnancesurvey.co.uk/cmd/local/v1.1 http://www.ordnancesurvey.co.uk/oswebsite/xml/cmdschema/local/V1.1/CMDFeatures.xsd");
_writer.WriteAttributeString("fid", ""); // TODO: set fid here

_writer.WriteStartElement("description", "http://www.opengis.net/gml");
_writer.WriteValue("Ordnance Survey, (c) Crown Copyright. All rights reserved, 2011-03-02");
_writer.WriteEndElement(); // description

_writer.WriteElementString("creationDate", "http://namespaces.ordnancesurvey.co.uk/cmd/local/v1.1", DateTime.Today.ToString("yyyy-MM-dd"));
_writer.WriteEndElement();

(Personally I would use LINQ to XML, which makes all of this much simpler, but hey...)

As a hint, always assume that your code is wrong rather than the framework code, as a starting point. Regarding a framework class as "stupid" is likely to lead to you not looking at your own code with sufficient care.

EDIT: Here's working LINQ to XML code:

using System;
using System.Xml.Linq;

static class Test
{
    static void Main()
    {
        XNamespace osgb = "http://namespaces.ordnancesurvey.co.uk/cmd/local/v1.1";
        XNamespace gml = "http://www.opengis.net/gml";
        XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";

        var doc = new XDocument(
            new XElement(osgb + "FeatureCollection",
               new XAttribute(XNamespace.Xmlns + "osgb", osgb),
               new XAttribute(XNamespace.Xmlns + "gml", gml),
               new XAttribute(XNamespace.Xmlns + "xsi", xsi),
               new XAttribute(xsi + "schemaLocation", "http://namespaces.ordnancesurvey.co.uk/cmd/local/v1.1 http://www.ordnancesurvey.co.uk/oswebsite/xml/cmdschema/local/V1.1/CMDFeatures.xsd"),
               new XAttribute("fid", ""),
               new XElement(gml + "description", "Ordnance Survey ..."),
               new XElement(osgb + "creationDate",
                            // TODO: Find a better way of doing this
                            DateTime.Today.ToString("yyyy-MM-dd"))));
        Console.WriteLine(doc);
   }
}

Output:

<osgb:FeatureCollection
    xmlns:osgb="http://namespaces.ordnancesurvey.co.uk/cmd/local/v1.1" 
    xmlns:gml="http://www.opengis.net/gml"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://namespaces.ordnancesurvey.co.uk/cmd/local/v1.1 http://www.ordnancesurvey.co.uk/oswebsite/xml/cmdschema/local/V1.1/CMDFeatures.xsd"
    fid="">
  <gml:description>Ordnance Survey ...</gml:description>
  <osgb:creationDate>2012-10-19</osgb:creationDate>
</osgb:FeatureCollection>

Upvotes: 8

Related Questions