C# with XDocument and xsi:schemaLocation - c#

I want to create the following XML.
<?xml version="1.0" encoding="utf-8"?>
<MyNode xsi:schemaLocation="https://MyScheme.com/v1-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://MyScheme.com/v1-0 Sscheme.xsd">
<MyInfo>
<MyNumber>string1</MyNumber>
<MyName>string2</MyName>
<MyAddress>string3</MyAddress>
</MyInfo>
<MyInfo2>
<FirstName>string4</FirstName>
</MyInfo2>
</MyNode>
I'm using this code.
XNamespace xmlns = "https://MyScheme.com/v1-0 Sscheme.xsd";
XNamespace xsi = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance");
XNamespace schemaLocation = XNamespace.Get("https://MyScheme.com/v1-0");
XDocument xmlDocument = new XDocument(
new XElement(xmlns + "MyNode",
new XAttribute(xsi + "schemaLocation", schemaLocation),
new XAttribute(XNamespace.Xmlns + "xsi", xsi),
new XElement("MyInfo",
new XElement("MyNumber", "string1"),
new XElement("MyName", "string2"),
new XElement("MyAddress", "string3")
),
new XElement("MyInfo2",
new XElement("FirstName", "string4")
)
)
);
xmlDocument.Save("C:\\MyXml.xml");
However, I'm getting xmlns="" inside tags MyInfo and MyInfo2.
Can somebody help me to create the correct XML?

You need to use xmlns XNamespace for all elements, because that is default namespace and it is declared at root level element. Note that descendant elements inherit ancestor default namespace implicitly, unless otherwise specified :
XDocument xmlDocument = new XDocument(
new XElement(xmlns + "MyNode",
new XAttribute(xsi + "schemaLocation", schemaLocation),
new XAttribute(XNamespace.Xmlns + "xsi", xsi),
new XElement(xmlns+"MyInfo",
new XElement(xmlns+"MyNumber", "string1"),
new XElement(xmlns+"MyName", "string2"),
new XElement(xmlns+"MyAddress", "string3")
),
new XElement(xmlns+"MyInfo2",
new XElement(xmlns+"FirstName", "string4")
)
)
);
Dotnetfiddle Demo

Related

Error parsing xml syntax error

I have the following code below. I am getting an error "the character ':' hexadecimal value 0x3A cannot be included in a name" Can anyone tell me how to fix this?
Thanks Below is the entire code
public static XDocument GenerateXMLSpreadSheet(DataTable tbl)
{
new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XProcessing**Instruction("mso-application", "Excel.Sheet"),
new XElement("Workbook",
new XAttribute("xmlns", "urn:schemas-microsoft-com:office:spreadsheet"),
new XAttribute("xmlns:ss", "urn:schemas-microsoft-
com:office:spreadsheet"),
new XElement("Worksheet", new XAttribute("ss:Name",
tbl.TableName),
new XElement("Table", GetRows(tbl)
)
)
)
);
return xmlssDoc;
)
public static Object[] GetRows(DataTable tbl)
{
// generate XElement rows for each row in the database.
// generate from the bottom-up.
// start with the cells.
XElement[] rows = new XElement[tbl.Rows.Count];
int r = 0;
foreach (DataRow row in tbl.Rows)
{
// create the array of cells to add to the row:
XElement[] cells = new XElement[tbl.Columns.Count];
int c = 0;
foreach (DataColumn col in tbl.Columns)
{
cells[c++] =
new XElement("Cell",
new XElement("Data", new XAttribute("ss:Type", "String"),
new XText(row[col].ToString())));
}
rows[r++] = new XElement("Row", cells);
}
// return the array of rows.
return rows;
}
Basically, that's not how you handle namespaces in LINQ to XML. You never specify a string with a colon in - instead, you build up an XName from an XNamespace and a string.
The good news is that LINQ to XML handling of namespaces is simple. Here's a complete example:
using System;
using System.Xml.Linq;
public class Test
{
static void Main(string[] args)
{
XNamespace ns = "urn:schemas-microsoft-com:office:spreadsheet";
var doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XProcessingInstruction("mso-application", "Excel.Sheet"),
new XElement(ns + "Workbook",
new XAttribute("xmlns", ns),
new XAttribute(XNamespace.Xmlns + "ss", ns),
new XElement(ns + "Worksheet",
new XAttribute(ns + "Name", "my-table-name"),
new XElement(ns + "Table")
)
)
);
Console.WriteLine(doc);
}
}
Output (reformatted for clarity):
<?mso-application Excel.Sheet?>
<ss:Workbook
xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
<ss:Worksheet ss:Name="my-table-name">
<ss:Table />
</ss:Worksheet>
</ss:Workbook>
Note how you need to specify the namespace for all the elements and attributes.
Because you've specified an explicit prefix for the namespace, LINQ to XML uses it everywhere. If you remove this part:
new XAttribute(XNamespace.Xmlns + "ss", ns)
... then the namespace for elements will be defaulted, and LINQ to XML will generate a prefix for the attributes that need it explicitly specified (as attributes don't default their namespaces).
Then the output is (for example):
<?mso-application Excel.Sheet?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet">
<Worksheet p2:Name="my-table-name" xmlns:p2="urn:schemas-microsoft-com:office:spreadsheet">
<Table />
</Worksheet>
</Workbook>
The problem is how you defined namespaces.
To work with namespaces you may get one by calling XNamespace.Get("the namespace") and using this everywhere you want.
And for xmlns you may use static property XNamespace.Xmlns.
So the final code will look like:
new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XProcessingInstruction("mso-application", "Excel.Sheet"),
new XElement("Workbook",
new XAttribute("xmlns", ns),
new XAttribute(XNamespace.Xmlns + "ss", ns),
new XElement("Worksheet", new XAttribute(ns + "Name",
tbl.TableName),
new XElement("Table", GetRows(tbl)
)
)
)
);

How to add xmlns to xml document?

I'm trying to create a fairly simple XML document that looks like this.
<?xml version="1.0" encoding="UTF-8"?>
<employees xmlns="http://website.com/xsd/MQ">
<employee>
<id>00122731</id>
<first-name>LUIS</first-name>
<last-name>GARCIA</last-name>
<subarea>4100</subarea>
<cost-center>904</cost-center>
<email-address>L.GARCIA#EMAIL.COM</email-address>
</employee>
</employees>
I was able to get the basics by using this code but I need to add the xmlns attribute and I'm not figuring out how to do that.
var xmlDoc = new XElement("employees",
from e in listEmployees
select new XElement("employee",
new XElement("id", e.EmployeeId),
new XElement("first-name", e.FirstName),
new XElement("last-name", e.LastName),
new XElement("subarea", e.SubArea),
new XElement("cost-center", e.CostCenter),
new XElement("email-address", e.EmailAddress)));
This is my attempt to add it but I get an error that this would cause and invalid structure.
XDocument xmlDoc = new XDocument(
new XElement("employees",
new XAttribute("xmlns", "http://website/xsd/MQ")),
from e in listEmployees
select new XElement("employee",
new XElement("id", e.EmployeeId),
new XElement("first-name", e.FirstName),
new XElement("last-name", e.LastName),
new XElement("subarea", e.SubArea),
new XElement("cost-center", e.CostCenter),
new XElement("email-address", e.EmailAddress))
);
UPDATE
Based on the link provided below this is what I came up with that worked.
XNamespace ns = "http://website/xsd/MQ";
var xmlDoc = new XElement(ns + "employees",
from e in listEmployees
select new XElement("employee",
new XElement("id", e.EmployeeId),
new XElement("first-name", e.FirstName),
new XElement("last-name", e.LastName),
new XElement("subarea", e.SubArea),
new XElement("cost-center", e.CostCenter),
new XElement("email-address", e.EmailAddress)));
You need to include the namespace on all of your elements, not just the top one:
XNamespace ns = "http://website/xsd/MQ";
var xmlDoc = new XElement(ns + "employees",
from e in listEmployees
select new XElement(ns + "employee",
new XElement(ns + "id", e.EmployeeId),
new XElement(ns + "first-name", e.FirstName),
new XElement(ns + "last-name", e.LastName),
new XElement(ns + "subarea", e.SubArea),
new XElement(ns + "cost-center", e.CostCenter),
new XElement(ns + "email-address", e.EmailAddress)
)
);
If that's too repetitive for you, you could make a convenience method:
XNamespace ns = "http://website/xsd/MQ";
private static XElement MQElement(string name, object contents)
{
return new XElement(ns + name, contents);
}
then use it:
var xmlDoc = MQElement("employees",
from e in listEmployees
select MQElement("employee",
MQElement("id", e.EmployeeId),
MQElement("first-name", e.FirstName),
MQElement("last-name", e.LastName),
MQElement("subarea", e.SubArea),
MQElement("cost-center", e.CostCenter),
MQElement("email-address", e.EmailAddress)
)
);
One more option to achieve same result is to construct XElement ignoring namespaces completely and then add them in separate code:
foreach (XElement e in xmlDoc.DescendantsAndSelf())
{
if (e.Name.Namespace == "")
{
e.Name = ns + e.Name.LocalName;
}
}

C# XML - Why does this Code keep failing with 0x3A Error?

i have following code example:
PlentySoapRequest_GetAuthentificationToken username = new PlentySoapRequest_GetAuthentificationToken();
username.Username = user_textbox.ToString();
username.Userpass = password_textbox.ToString();
Uri uri = new Uri("http://www.****.de/plenty/api/soap/version105/");
XNamespace soapenv = #"http://schemas.xmlsoap.org/soap/envelope/";
XNamespace xsi = #"http://www.w3.org/2001/XMLSchema-instance";
XNamespace xsd = #"http://www.w3.org/2001/XMLSchema";
XNamespace ver = #"http://www.****.de/plenty/api/soap/version105/";
var document = new XDocument(
new XDeclaration("1.0", "utf-8", String.Empty),
new XElement(soapenv + "Envelope",
new XAttribute(XNamespace.Xmlns + "xsi", xsi),
new XAttribute(XNamespace.Xmlns + "xsd" , xsd),
new XAttribute(XNamespace.Xmlns + "soapenv" , soapenv),
new XAttribute(XNamespace.Xmlns + "ver" , ver),
new XElement(soapenv + "Header"),
new XElement(soapenv + "Body",
new XElement(ver + "GetAuthentificationToken",
new XElement("oLogin" + xsi + "type" + ver + "PlentySoapRequest_GetAuthentificationToken",
new XAttribute("Username" + xsi + "type" + xsd + "string", username.Username),
new XAttribute("Userpass" + xsi + "type" + xsd + "string", username.Userpass)
)
)
)
)
);
I keep getting the error message in the first line. "plentysoaprequest...."
The ':' character, hexadecimal value 0x3A, cannot be included in a name.
if I comment out those lines, it keeps say it is in the first line of the code.
Edit:
the xml should look like this:
<soapenv:Body>
<ver:GetAuthentificationToken>
<oLogin xsi:type="ver:PlentySoapRequest_GetAuthentificationToken">
<!--You may enter the following 2 items in any order-->
<Username xsi:type="xsd:string">apitest</Username>
<Userpass xsi:type="xsd:string">apitest</Userpass>
</oLogin>
</ver:GetAuthentificationToken>
so there seems to be a problem with the xml-sysntax.
I cant figure out how to set xsi:type or xsi:type
"oLogin" + xsi + "type" will create a string with value "oLoginhttp://www.w3.org/2001/XMLSchema-instancetype". That's not a valid name...
You need something a little closer to this:
var document = new XDocument(
new XDeclaration("1.0", "utf-8", String.Empty),
new XElement(soapenv + "Envelope",
new XAttribute(XNamespace.Xmlns + "xsi", xsi),
new XAttribute(XNamespace.Xmlns + "xsd", xsd),
new XAttribute(XNamespace.Xmlns + "soapenv", soapenv),
new XAttribute(XNamespace.Xmlns + "ver", ver),
new XElement(soapenv + "Header"),
new XElement(soapenv + "Body",
new XElement(ver + "GetAuthentificationToken",
new XElement(xsi + "Login",
new XAttribute(xsi + "type", "blahblah"),
new XElement("Username",
new XAttribute(xsi + "type", "xsd:string"),
"myUserName")
)
)
)
)
);
Which generates this XML
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ver="http://www.****.de/plenty/api/soap/version105/">
<soapenv:Header />
<soapenv:Body>
<ver:GetAuthentificationToken>
<xsi:Login xsi:type="blahblah">
<Username xsi:type="xsd:string">myUserName</Username>
</xsi:Login>
</ver:GetAuthentificationToken>
</soapenv:Body>
</soapenv:Envelope>

How to create an Xml with multiple namescapes using XDocument

I would like to create a document with multiple namespaces (see Xml below). How can I do that using XDocument? My final result should the following:
<?xml version="1.0" encoding="utf-8"?>
<a:feed xmlns:a="http://www.w3.org/2005/Atom" xmlns:os="http://a9.com/-/spec/opensearch/1.1/" xmlns="http://schemas.zune.net/catalog/apps/2008/02">
<a:link rel="prev" type="application/atom+xml" href="myUrl" />
<a:link rel="next" type="application/atom+xml" href="myUrl" />
<a:link rel="self" type="application/atom+xml" href="myUrl" />
<a:updated>2008-05-20T22:50:46.7932864Z</a:updated>
Here is the code I have so far.
XNamespace nsW3Atom = "http://www.w3.org/2005/Atom";
XNamespace nsOs = "http://a9.com/-/spec/opensearch/1.1/";
XNamespace nsZune = "http://schemas.zune.net/calatog/apps/2008/02";
XDocument doc =
new XDocument(
// new XDeclaration("1.0", "utf-8", "no"),
new XElement("feed",
new XAttribute("a", nsW3Atom),
new XAttribute("os", nsOs),
new XAttribute("os2", nsZune),
new XElement(XNamespace.Xmlns + "link", new XAttribute("rel", "prev"), new XAttribute("type", "application/atom+xml")),
new XElement(XNamespace.Xmlns + "link", new XAttribute("rel", "next"), new XAttribute("type", "application/atom+xml")),
new XElement(XNamespace.Xmlns + "link", new XAttribute("rel", "self"), new XAttribute("type", "application/atom+xml"))));
Thank you in advance for the help!
XNamespace a="http://www.w3.org/2005/Atom";
XNamespace os = "http://a9.com/-/spec/opensearch/1.1/";
XNamespace def = "http://schemas.zune.net/catalog/apps/2008/02";
var doc =
new XDocument(new XElement(a + "feed",
new XAttribute(XNamespace.Xmlns + "a", a),
new XAttribute(XNamespace.Xmlns + "os", os),
new XAttribute("xmlns", def)));
then if You want to use the a Namespace, prefix any element with a+
When creating the attributes use the xmlns: prefix.
new XAttribute("xmlns:a", nsW3Atom),
new XAttribute("xmlns:os", nsOs),
new XAttribute("xmlns:os2", nsZune)

How to generate xsi:schemalocation attribute correctly when generating a dynamic sitemap.xml with LINQ to XML?

I am generating a dynamic sitemap.xml
According to sitemaps.org this is the header for a sitemap.xml
<?xml version='1.0' encoding='UTF-8'?>
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
...
</url>
</urlset>
So I'm using LINQ To XML to generate the sitemap.xml
XNamespace ns = "http://www.sitemaps.org/schemas/sitemap/0.9";
return new XElement(ns + "urlset",
new XAttribute("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9"),
new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"),
//new XAttribute("xsi:schemaLocation", "http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"),
from node in new GetNodes()
select new XElement(ns + "url",
new XElement(ns + "loc", node.Loc),
new XElement(ns + "lastmod", node.LastMod),
new XElement(ns + "priority", node.Priority)
)
).ToString();
The commented line is the one i cannot get right.
How can i set the "xsi:schemalocation" attribute?
Thanks.
Ok, I got it right. Thanks to Mike Caron
If I declare the XAtrribute(XNamespace.Xmlns + "xsi",...) then it works
XNamespace ns = "http://www.sitemaps.org/schemas/sitemap/0.9";
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
return new XElement(ns + "urlset",
new XAttribute("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9"),
new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"),
new XAttribute(xsi + "schemaLocation", "http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"),
from node in GetNodes()
select new XElement(ns + "url",
new XElement(ns + "loc", node.Loc),
new XElement(ns + "lastmod", node.LastMod),
new XElement(ns + "priority", node.Priority)
)
).ToString();
I don't know LINQ to XML, but after a quick peek at the documentation, try this:
XNamespace ns = "http://www.sitemaps.org/schemas/sitemap/0.9";
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
return new XElement(ns + "urlset",
new XAttribute(xsi + "schemaLocation", "http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"),
from node in new GetNodes()
select new XElement(ns + "url",
new XElement(ns + "loc", node.Loc),
new XElement(ns + "lastmod", node.LastMod),
new XElement(ns + "priority", node.Priority)
)
).ToString();
Note that I'm not setting the xmlns attributes explicitly. I suspect they're generated automatically. Also, caveat emptor, since this is not tested.

Categories