Generating namespaced XML - c#

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);

Related

How do I create an XElement that contains a prefix without a wrapper?

I'm trying to create a simple empty XElement like this:
<dyn:Positions>
<Vector2-Array>
</Vector2-Array>
</dyn:Positions>
I have the namespace defined above:
XNamespace dyn = "https://www.abc.at/dyn";
But when I create the XElement:
XElement positions = new XElement(dyn + "Positions", new XElement("Vector2-Array"));
It comes out like this:
<Positions xmlns="dyn">
<Vector2-Array xmlns="" />
</Positions>
Is that possible without wrapping it in another XElement? Because I need this element to be appended in another document later, after more elements are added inside.
I think you want Vector2-Array to be in the same namespace as Positions, and then you don't see it in the output:
XElement positions = new XElement(dyn + "Positions",
new XElement(dyn + "Vector2-Array"));
this gives
<Positions xmlns="https://www.abc.at/dyn">
<Vector2-Array />
</Positions>
the dyn: notation is just a shorthand, it should not matter when you later merge this in some parent XML. You should be very sure about which namespace everything belongs to.
Because you're not adding your namespace declaration, the dyn namespace becomes the default.
Then, when you add the child element without a namespace, a namespace declaration with no namespace has to be added to indicate it is not within the default namespace.
If your dyn namespace is not meant to be the default namespace, try the following code:
XNamespace dyn = "https://www.abc.at/dyn";
XElement positions = new XElement(
dyn + "Positions",
new XAttribute(XNamespace.Xmlns + "dyn", "https://www.abc.at/dyn"),
new XElement("Vector2-Array"));
This produces the following output:
<dyn:Positions xmlns:dyn="https://www.abc.at/dyn">
<Vector2-Array />
</dyn:Positions>
Note that when you start appending this element to other documents, you may get more behaviour similar to your original problem if there's any mismatches of namespaces.
The OP has specifically brought up the subject of appending this element to another element that also contains the namespace declaration.
I've created this code to test:
XNamespace dyn = "https://www.abc.at/dyn";
XElement positions = new XElement(
dyn + "Positions",
new XAttribute(XNamespace.Xmlns + "dyn", "https://www.abc.at/dyn"),
new XElement("Vector2-Array"));
XElement root = new XElement(
dyn + "root",
new XAttribute(XNamespace.Xmlns + "dyn", "https://www.abc.at/dyn"));
root.Add(positions);
When using the debugger, the XML of the root element after adding Positions is this:
<dyn:root xmlns:dyn="https://www.abc.at/dyn">
<dyn:Positions xmlns:dyn="https://www.abc.at/dyn">
<Vector2-Array />
</dyn:Positions>
</dyn:root>
So the namespace declaration is duplicated.
However, there is a SaveOption of OmitDuplicateNamespaces that can be used when saving or formatting the XML to string:
Console.WriteLine(root.ToString(SaveOptions.OmitDuplicateNamespaces));
The resulting output of this is as below:
<dyn:root xmlns:dyn="https://www.abc.at/dyn">
<dyn:Positions>
<Vector2-Array />
</dyn:Positions>
</dyn:root>
Because the duplicate namespace declarations effectively do nothing (even though they're ugly) they can be removed this way, if the displaying of the XML is the important thing.
Functionally, having duplicated namespace declarations doesn't actually do anything as long as they match.

linq to xml duplicate namespace gives empty attribute

<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.

Create XML Amazon Envelope in C#

I'm trying to create XML file necessary for Amazon's feed but getting error when creating AmazonEnvelope
XElement _POST_PRODUCT_DATA_ = new XElement(#"AmazonEnvelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance\"" xsi:noNamespaceSchemaLocation=""amzn-envelope.xsd""");
_POST_PRODUCT_DATA_.Save("D:\\_POST_PRODUCT_DATA_.xml");
The error says:
+ $exception {"The ' ' character, hexadecimal value 0x20, cannot be included in a name."} System.Exception {System.Xml.XmlException}
Problem is, there have to be space. Does anyone have solution for it?
Use object model instead of "everything-in-plain-text" method
XNamespace ns = "http://www.w3.org/2001/XMLSchema-instance";
var elm = new XElement("AmazonEnvelope",
new XAttribute(XNamespace.Xmlns + "xsi", ns),
new XAttribute(ns + "noNamespaceSchemaLocation", "amzn-envelope.xsd"));

The prefix " cannot be redefined from " to <url> within the same start element tag

I'm trying to generate the following xml element using C#.
<Foo xmlns="http://schemas.foo.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://schemas.foo.com
http://schemas.foo.com/Current/xsd/Foo.xsd">
The problem that I'm having is that I get the exception:
The prefix " cannot be redefined from " to within the same start
element tag.
This is my c# code:
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
XElement foo = new XElement("Foo", new XAttribute("xmlns", "http://schemas.foo.com"),
new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"),
new XAttribute(xsi + "schemaLocation", "http://schemas.foo.com http://schemas.foo.com/Current/xsd/Foo.xsd"));
How can I fix this? I'm trying to send the generated xml as the body of a SOAP message and I need it to be in this format for the receiver.
EDIT: I found my answer on another question. Controlling the order of XML namepaces
You need to indicate that the element Foo is part of the namespace http://schemas.foo.com. Try this:
XNamespace xNamespace = "http://schemas.foo.com";
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
XElement foo = new XElement(
xNamespace + "Foo",
new XAttribute("xmlns", "http://schemas.foo.com"),
new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"),
new XAttribute(xsi + "schemaLocation", "http://schemas.foo.com http://schemas.foo.com/Current/xsd/Foo.xsd")
);
I was getting this error when creating an XDocument. After a lot of googling I found this article:
http://www.mikesdotnetting.com/Article/111/RSS-Feeds-and-Google-Sitemaps-for-ASP.NET-MVC-with-LINQ-To-XML
There just happens to be an explanation part way through the doc, that I was lucky enough to spot.
The key point is that your code should let the XDocument handle the xmlns attribute. When creating an XElement, your first instinct would be to set the namespace attribute like all the rest, by adding an attribute "xmlns" and setting it to a value.
Instead, you should create an XNamespace variable, and use that XNamespace variable when defining the XElement. This will effectively add an XAttribute to your element for you.
When you add an xmlns attribute yourself, you are telling the XElement creation routine to create an XElement in no namespace, and then to change the namespace using the reserved xmlns attribute. You are contradicting yourself. The error says "You cannot set the namespace to empty, and then set the namespace again to something else in the same tag, you numpty."
The function below illustrates this...
private static void Test_Namespace_Error(bool doAnError)
{
XDocument xDoc = new XDocument();
string ns = "http://mynamespace.com";
XElement xEl = null;
if (doAnError)
{
// WRONG: This creates an element with no namespace and then changes the namespace
xEl = new XElement("tagName", new XAttribute("xmlns", ns));
}
else
{
// RIGHT: This creates an element in a namespace, and implicitly adds an xmlns tag
XNamespace xNs = ns;
xEl = new XElement(xNs + "tagName");
}
xDoc.Add(xEl);
Console.WriteLine(xDoc.ToString());
}
Others explain why this is happening but it still took me a while to work out how to fix it for me. I was trying to add some external XML to an XML document.
What finally worked for me was:
ElementTree.register_namespace("mstts", "https://www.w3.org/2001/mstts")
ElementTree.register_namespace("", "http://www.w3.org/2001/10/synthesis")
xml_body = ElementTree.fromstring(
'<speak version="1.0"'
' xmlns:mstts="https://www.w3.org/2001/mstts"'
' xmlns="http://www.w3.org/2001/10/synthesis"'
f' xml:lang="{locale}">'
f' <voice name="{azure_voice}">'
' <mstts:silence type="Leading" value="0" />'
' <prosody rate="-10.00%">'
f' {utterance}'
' </prosody>'
' <mstts:silence type="Tailing" value="0" />'
' </voice>'
'</speak>'

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"
)
);
}

Categories

Resources