Create XML Amazon Envelope in C# - 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"));

Related

Little help using XmlTextWriter on writing "xhtml:link" element of sitemap.xml

Hello I'm trying to write a string like :
<xhtml:link rel="alternate" hreflang="de" href="http://www.example.com/de" />
using XmlTextWriter class
I've tried this piece of code:
// Write Alternative links
_writer.WriteStartElement("xhtml:link");
_writer.WriteAttributeString("rel","alternate");
_writer.WriteAttributeString("hreflang", "de");
_writer.WriteAttributeString("href", "http://example.com/de");
_writer.WriteEndElement();
Which generates this error:
Namespace prefix xhtml on link is not defined
But I don't need any namespaces provided for xhtml:link
Question: How to achieve the string that I need using XmlTextWriter?
Update 1: I have changed to LINQ to XML
But for now I have another problem... For the beginning I'll show the code:
private readonly XNamespace nsXhtml = "http://www.w3.org/1999/xhtml";
private readonly XNamespace nsSitemap = "http://www.sitemaps.org/schemas/sitemap/0.9";
private readonly XNamespace nsXsi = "http://www.w3.org/2001/XMLSchema-instance";
private readonly XNamespace nsLocation = "http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd";
public XDocument Generate()
{
var sitemap = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
var urlSet = new XElement(nsSitemap + "urlset",
new XAttribute("xmlns", nsSitemap),
new XAttribute(XNamespace.Xmlns + "xhtml", nsXhtml),
new XAttribute(XNamespace.Xmlns + "xsi", nsXsi),
new XAttribute(nsXsi + "schemaLocation", nsLocation),
from node in GenerateUrlNodes() // Provides a collection of "objects", actually it doesn't matter since we anyway convert them to XElement below...
select WriteUrlLocation(node.Url,node.UpdateFrequency,node.LastModified));
sitemap.Add(urlSet);
return sitemap;
}
protected XElement WriteUrlLocation(string url, UpdateFrequency updateFrequency, DateTime lastUpdated)
{
var urlNode = new XElement(nsSitemap + "url",
new XElement(nsSitemap + "loc", url),
new XElement(nsSitemap + "changefreq", updateFrequency),
new XElement(nsSitemap + "lastmod", lastUpdated)
);
var linkNode = new XElement(nsXhtml + "link",
new XAttribute("rel", "alternate"),
new XAttribute("hreflang", "de"),
new XAttribute("href", "http://example.com/de"));
urlNode.Add(linkNode);
return urlNode;
}
The problem is that When I inspect the Generated sitemap at Controller:
public ActionResult Sitemap()
{
var sitemap = _sitemapGenerator.Generate().ToString();
return Content(sitemap,"text/xml");
}
The whole xml is not as expected and, the <xhtml:link> element is rendered with a non-empty closing tag (thus I don't know if this is a problem here) .. Look at the image please
Update 2: Solved! Seems that the XML structure is valid but the browser is not displaying it right...
You should change to use a different overload of XmlWriter.StartElement. For example:
_writer.WriteStartElement("link", "http://www.w3.org/1999/xhtml");
That assumes you've already got a prefix alias of xhtml for the namespace http://www.w3.org/1999/xhtml. I'd still recommend shifting to use LINQ to XML as soon as you can though... XmlWriter is great for cases where you really need to stream the data (e.g. when it's huge) but otherwise, LINQ to XML makes things a lot easier:
XNamespace xhtml = "http://www.w3.org/1999/xhtml";
var element = new XElement(xhtml + "link",
new XAttribute("rel", "alternate"),
new XAttribute("hreflang", "de"),
new XAttribute("href", "http://example.com/de"));
parent.Add(element);
If you will use XML Writer and write this
<xhtml:link rel="alternate" hreflang="en" href="www.yoursite.com" />
you can choose this code for .NET CORE 2.0:
foreach (SitemapNodeAlternate a in alternate)
{
MyWriter.WriteStartElement("xhtml", "link", null);
MyWriter.WriteAttributeString("rel", "alternate");
MyWriter.WriteAttributeString("href", a.href);
MyWriter.WriteAttributeString("hreflang", a.hreflang);
MyWriter.WriteEndElement();
}

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

Adding child nodes using c# Xdocument class

I have an xml file as given below.
<?xml version="1.0" encoding="utf-8"?>
<file:Situattion xmlns:file="test">
<file:Properties>
</file:Situattion>
I would like to add the child element file:Character using xDocument.So that my final xml would be like given below
<?xml version="1.0" encoding="utf-8"?>
<file:Situattion xmlns:file="test">
<file:Characters>
<file:Character file:ID="File0">
<file:Value>value0</file:Value>
<file:Description>
Description0
</file:Description>
</file:Character>
<file:Character file:ID="File1">
<file:Value>value1</file:Value>
<file:Description>
Description1
</file:Description>
</file:Character>
</file:Characters>
Code in c# i tried using Xdocument class is given below.
XNamespace ns = "test";
Document = XDocument.Load(Folderpath + "\\File.test");
if (Document.Descendants(ns + "Characters") != null)
{
Document.Add(new XElement(ns + "Character"));
}
Document.Save(Folderpath + "\\File.test");
At line "Document.Add(new XElement(ns + "Character"));", I am getting an error:
"This operation would create an incorrectly structured document.".
How can I add the node under "file:Characters".
You're trying to add an extra file:Character element directly into the root. You don't want to do that - you want to add it under the file:Characters element, presumably.
Also note that Descendants() will never return null - it will return an empty sequence if there are no matching elements. So you want:
var ns = "test";
var file = Path.Combine(folderPath, "File.test");
var doc = XDocument.Load(file);
// Or var characters = document.Root.Element(ns + "Characters")
var characters = document.Descendants(ns + "Characters").FirstOrDefault();
if (characters != null)
{
characters.Add(new XElement(ns + "Character");
doc.Save(file);
}
Note that I've used more conventional naming, Path.Combine, and also moved the Save call so that you'll only end up saving if you've actually made a change to the document.
Document.Root.Element("Characters").Add(new XElement("Character", new XAttribute("ID", "File0"), new XElement("Value", "value0"), new XElement("Description")),
new XElement("Character", new XAttribute("ID", "File1"), new XElement("Value", "value1"), new XElement("Description")));
Note: I have not included the namespace for brevity. You have to add those.

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

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