Creating XElement with namespaces?

112 views Asked by At

I am trying to get to the following XML (for a 3rd party; so needs to be exact) and having some trouble with the xmlns on the inner elements:

<headerResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <sessionID xmlns="http://www.example.com/portal-api">4654654564</sessionID>
  <uniqueTranID xmlns="http://www.example.com/portal-api">gh0000000</uniqueTranID>
  <statusCode xmlns="http://www.example.com/portal-api">1</statusCode>
  <statusCodeDescription xmlns="http://www.example.com/portal-api">jhkjhkjhkjhkjkjhkjkkjhkhk</statusCodeDescription>
  <message xmlns="http://www.example.com/portal-api">testMessage</message>
</headerResponse>

From other examples, I have got the following:

XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
XNamespace xsd = "http://www.w3.org/2001/XMLSchema";
XNamespace api = "http://www.example.com/portal-api";

XElement example = new XElement("headerResponse",
  new XAttribute(XNamespace.Xmlns + "xsi", xsi),
  new XAttribute(XNamespace.Xmlns + "xsd", xsd),
  new XElement("sessionID", "some session id", new XAttribute("xmlns", api))
);

Without the sessionID, it happily created the main headerResponse with the xsi and xsd, but when I added the sessionID in and try to post the contents in the immediate window with example.toString(), I get the following error:

The prefix '' cannot be redefined from '' to 'http://www.example.com/portal-api' within the same start element tag.
1

There are 1 answers

1
Charles Mager On BEST ANSWER

You need to define your element name sessionID with its fully qualified name (i.e. including its namespace). The insertion of a default namespace declaration will be handled automatically by LINQ to XML:

XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
XNamespace xsd = "http://www.w3.org/2001/XMLSchema";
XNamespace api = "http://www.example.com/portal-api";

XElement example = new XElement("headerResponse",
    new XAttribute(XNamespace.Xmlns + "xsi", xsi),
    new XAttribute(XNamespace.Xmlns + "xsd", xsd),
    new XElement(api + "sessionID", "some session id")
);   

You can control the declarations by adding them as you've already done. For example, you could add a declaration for api with a prefix to the root to simplify the result:

XElement example = new XElement("headerResponse",
    new XAttribute(XNamespace.Xmlns + "xsi", xsi),
    new XAttribute(XNamespace.Xmlns + "xsd", xsd),
    new XAttribute(XNamespace.Xmlns + "api", api),
    new XElement(api + "sessionID", "some session id")
);   

Note that although the XML would look different to your required XML, there is semantically no difference between them.