linq to xml duplicate namespace gives empty attribute - c#

<ftc:XX version="1.1"
xmlns:ftc="urn:v1"
xmlns="urn:v1">
<ftc:YY>
<SIN>000000</SIN>
<Country>CA</Country>
</ftc:YY>
</ftc:XX>
this is the what i need to create. but when i create this, it shows empty namespace in the SIN and Country tag. i need to remove that. can anyone guide me?
this is the code which i use,
XNamespace ftc = "urn:v1";
XElement XX = new XElement(ftc + "XX",
new XAttribute(XNamespace.Xmlns + "ftc", ftc.NamespaceName),
new XAttribute("xmlns", ftc.NamespaceName),
new XAttribute("version","1.1"),
new XElement(ftc + "YY",
XElement("SIN", "000000"),
new XElement("Country", "CA")
)
)
with this, what i get is like this.
<ftc:XX version="1.1"
xmlns:ftc="urn:v1"
xmlns="urn:v1">
<ftc:YY>
<SIN xmlns="">000000</SIN>
<Country xmlns="">CA</Country>
</ftc:YY>
</ftc:XX>
but i need without this part.
xmlns=""

SIN and Country belong to the urn:v1 namespace. Your document has a default namespace of urn:v1 so all elements without an explicit namespace prefix will belong to that namespace.
When you created those elements, they were in the empty namespace, so that extra namespace declaration needed to be generated.
XNamespace ftc = "urn:v1";
var doc = new XDocument(
new XElement(ftc + "XX",
new XAttribute("version", "1.1"),
new XAttribute(XNamespace.Xmlns + "ftc", ftc),
new XAttribute("xmlns", ftc),
new XElement(ftc + "YY",
new XElement(ftc + "SIN", "000000"),
new XElement(ftc + "Country", "CA")
)
)
);
<XX version="1.1" xmlns:ftc="urn:v1" xmlns="urn:v1">
<YY>
<SIN>000000</SIN>
<Country>CA</Country>
</YY>
</XX>
Note that since your explicit namespace ftc and the default namespace are equal, none of the prefixes will be generated as you expect. This isn't configurable on a per element level as far as I know.

Related

How to specify an xmlns for XDocument?

I tried:
textBox1.Text = new XDocument(new XDeclaration("1.0", "UTF-8", "yes"),
new XElement("root1", new XAttribute( "xmlns", #"http://example.com"), new XElement("a", "b"))
).ToString();
But I get:
The prefix '' cannot be redefined from '' to 'http://example.com' within the same start element tag.
I also tried substituting (according to an answer I found) :
XAttribute(XNamespace.Xmlns,...
But got an error as well.
Note: I'm not trying to have more than one xmlns in the document.
The way the XDocument API works with namespace-scoped names is as XName instances. These are fairly easy to work with, as long as you accept that an XML name isn't just a string, but a scoped identifier. Here's how I do it:
var ns = XNamespace.Get("http://example.com");
var doc = new XDocument(new XDeclaration("1.0", "utf-8", null));
var root = new XElement(ns + "root1", new XElement(ns + "a", "b"));
doc.Add(root);
Result:
<root1 xmlns="http://example.com">
<a>b</a>
</root1>
Note the + operator is overloaded to accept an XNamespace and a String to result in and XName instance.

Generating namespaced XML

I'm trying to add more claims to the ClaimTypesOffered element as shown below:
<fed:ClaimTypesOffered>
<auth:ClaimType Uri="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" Optional="true" xmlns:auth="http://docs.oasis-open.org/wsfed/authorization/200706">
<auth:DisplayName>Name</auth:DisplayName>
<auth:Description>The name of the subject.</auth:Description>
</auth:ClaimType>
</fed:ClaimTypesOffered>
There is a lot of namespace magic going on there and I am trying to work my way through it. Just getting the proper element name has been difficult. I have tried all of the following:
new XElement(XNamespace.Get("auth") + "ClaimType", "somedata");
gives
<ClaimType xmlns="auth">somedata</ClaimType>
and
new XElement(XName.Get("{http://docs.oasis-open.org/wsfed/authorization/200706}auth"), "somedata");
gives
<auth xmlns="http://docs.oasis-open.org/wsfed/authorization/200706">somedata</auth>
and
new XElement("auth:ClaimType", "somedata");
gives
System.Xml.XmlException : The ':' character, hexadecimal value 0x3A, cannot be included in a name.
I'm looking for help getting this further along, a full example of generating the claim including the attributes and inner elements would be awesome, even a small push in the right direction would be appreciated.
The key is defining the namespace on the parent element, then the child elements can use that namespace. Without the new XAttribute(XNamespace.Xmlns + "auth", auth.NamespaceName) the namespace is defined in the other ways as seen in the original question.
XNamespace fed = "http://docs.oasis-open.org/wsfed/federation/200706";
XNamespace auth = "http://docs.oasis-open.org/wsfed/authorization/200706";
XElement root = new XElement(auth + "ClaimType",
new XAttribute(XNamespace.Xmlns + "auth", auth.NamespaceName),
new XAttribute("Uri", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"),
new XAttribute("Optional", "true"),
new XElement(auth+"DisplayName", "EmployeeID"),
new XElement(auth+"Description", "The employee's designated ID number.")
);
Console.WriteLine(root);

Create XML doc by LINQ, add xmlns,xmlns:xsi to it

I try to create an GPX XML document by LINQ to XML.
Everything works great, except adding xmlns, xmlns:xsi attributes to the doc. By trying it different way I get different exceptions.
My code:
XDocument xDoc = new XDocument(
new XDeclaration("1.0", "UTF-8", "no"),
new XElement("gpx",
new XAttribute("creator", "XML tester"),
new XAttribute("version","1.1"),
new XElement("wpt",
new XAttribute("lat","7.0"),
new XAttribute("lon","19.0"),
new XElement("name","test"),
new XElement("sym","Car"))
));
The output should also contain this:
xmlns="http://www.topografix.com/GPX/1/1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
How can I add it by Linq to XML? I tried several ways but it does not work, exceptions during compile time.
See How to: Control Namespace Prefixes. You could use code like this:
XNamespace ns = "http://www.topografix.com/GPX/1/1";
XNamespace xsiNs = "http://www.w3.org/2001/XMLSchema-instance";
XDocument xDoc = new XDocument(
new XDeclaration("1.0", "UTF-8", "no"),
new XElement(ns + "gpx",
new XAttribute(XNamespace.Xmlns + "xsi", xsiNs),
new XAttribute(xsiNs + "schemaLocation",
"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"),
new XAttribute("creator", "XML tester"),
new XAttribute("version","1.1"),
new XElement(ns + "wpt",
new XAttribute("lat","7.0"),
new XAttribute("lon","19.0"),
new XElement(ns + "name","test"),
new XElement(ns + "sym","Car"))
));
You have to specify the namespace for each element, because that's what using xmlns this way means.
From http://www.falconwebtech.com/post/2010/06/03/Adding-schemaLocation-attribute-to-XElement-in-LINQ-to-XML.aspx:
To generate the following root node and namespaces:
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:SchemaLocation="http://www.foo.bar someSchema.xsd"
xmlns="http://www.foo.bar" >
</root>
Use the following code:
XNamespace xsi = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance");
XNamespace defaultNamespace = XNamespace.Get("http://www.foo.bar");
XElement doc = new XElement(
new XElement(defaultNamespace + "root",
new XAttribute(XNamespace.Xmlns + "xsi", xsi.NamespaceName),
new XAttribute(xsi + "schemaLocation", "http://www.foo.bar someSchema.xsd")
)
);
Be aware - if you want to add elements to the document, you need to specify the defaultNamespace in the element name or you will get xmlns="" added to your element. For example, to add a child element "count" to the above document, use:
xdoc.Add(new XElement(defaultNamespace + "count", 0)

Why am I getting the extra xmlns="" using LINQ to XML?

I'm using LINQ to XML to generate a piece of XML. Everything works great except I'm throwing in some empty namespace declarations somehow. Does anyone out there know what I'm doing incorrectly? Here is my code
private string SerializeInventory(IEnumerable<InventoryInformation> inventory)
{
var zones = inventory.Select(c => new {
c.ZoneId
, c.ZoneName
, c.Direction
}).Distinct();
XNamespace ns = "http://www.dummy-tmdd-address";
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
var xml = new XElement(ns + "InventoryList"
, new XAttribute(XNamespace.Xmlns + "xsi", xsi)
, zones.Select(station => new XElement("StationInventory"
, new XElement("station-id", station.ZoneId)
, new XElement("station-name", station.ZoneName)
, new XElement("station-travel-direction", station.Direction)
, new XElement("detector-list"
, inventory.Where(p => p.ZoneId == station.ZoneId).Select(plaza =>
new XElement("detector", new XElement("detector-id", plaza.PlazaId)))))));
xml.Save(#"c:\tmpXml\myXmlDoc.xml");
return xml.ToString();
}
And here is the resulting xml. I hope it renders correctly? The browser may hide the tags.
<InventoryList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.dummy-tmdd-address">
<StationInventory xmlns="">
<station-id>999</station-id>
<station-name>Zone 999-SEB</station-name>
<station-travel-direction>SEB</station-travel-direction>
<detector-list>
<detector>
<detector-id>7503</detector-id>
</detector>
<detector>
<detector-id>2705</detector-id>
</detector>
</detector-list>
</StationInventory>
</InventoryList>
Notice the empty namespace declaration in the first child element. Any ideas how I can remedy this? Any tips are of course appreciated.
Thanks All.
Because of the missing namespace in:
new XElement("StationInventory"...
This implicitly indicates the empty namespace "" for the StationInvetory element. You should do:
new XElement(ns + "StationInventory"...
Note that you must do this for any element you create that lives in the ns namespace. The XML serializer will make sure to qualify elements with the correct namespace prefix according to scope.
Want to add to Peter Lillevold's answer.
XML Attributes don't require namespase in their XName
In addition to casting string to Xname:
The {myNamespaseName} will be casted to XNamespase on casting of "{myNamespaseName}nodeName" to XName
Also, look to the code structure that simplifies reading of the constructor method:
private readonly XNamespace _defaultNamespace = "yourNamespace";
public XElement GetXmlNode()
{
return
new XElement(_defaultNamespace + "nodeName",
new XElement(_defaultNamespace + "nodeWithAttributes",
new XAttribute("attribute1Name", "valueOfAttribute1"),
new XAttribute("attribute2Name", "valueOfAttribute2"),
"valueOfnodeWithAttributes"
)
);
}
or
public XElement GetXmlNode()
{
return
new XElement("{myNamespaseName}nodeName",
new XElement("{myNamespaseName}nodeWithAttributes",
new XAttribute("attribute1Name", "valueOfAttribute1"),
new XAttribute("attribute2Name", "valueOfAttribute2"),
"valueOfnodeWithAttributes"
)
);
}

How do I add multiple Namespace declarations to an XDocument?

I'm using an XDocument to build an Xml document in a known structure. The structure I am trying to build is as follows:
<request xmlns:ns4="http://www.example.com/a" xmlns:ns3="http://www.example.com/b" xmlns:ns2="http://www.example.com/c" >
<requestId>d78d4056-a831-4c7d-a357-d14402f623fc</requestId>
....
</request>
Notice the "xmlns:nsX" attributes.
I am trying, without success, to add these attributes to my "request" element.
XNamespace ns4 = XNamespace.Get("http://www.example.com/a");
XNamespace ns3 = XNamespace.Get("http://www.example.com/b");
XNamespace ns2 = XNamespace.Get("http://www.example.com/c");
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "no"),
new XElement("request",
new XAttribute("ns4", ns4),
new XAttribute("ns3", ns3),
new XAttribute("ns2", ns2),
new XElement("requestId", Guid.NewGuid())
)
);
However, this produces the following:
<request ns4="http://www.example.com/a" ns3="http://www.example.com/b" ns2="http://www.example.com/c">
<requestId>38b07cfb-5e41-4d9a-97c8-4740c0432f11</requestId>
</request>
How do I add the namespace declarations correctly?
Do you mean:
new XAttribute(XNamespace.Xmlns + "ns4", ns4),
new XAttribute(XNamespace.Xmlns + "ns3", ns3),
new XAttribute(XNamespace.Xmlns + "ns2", ns2),

Categories

Resources