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