1

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

enter image description here

Update 2: Solved! Seems that the XML structure is valid but the browser is not displaying it right...

Cristian E.
  • 3,116
  • 7
  • 31
  • 61
  • Do you absolutely *have* to use XmlTextWriter? Using something like LINQ to XML makes all kinds of things simpler. – Jon Skeet Aug 04 '14 at 12:30
  • Unfortunately yes, because I already have some work done in this style... But If there won't be any solutions i'll take in account your advice. – Cristian E. Aug 04 '14 at 12:32
  • Well there *are* solutions to this - it's just that the more you write in this painful style, the more work it'll be to move to LINQ to XML... – Jon Skeet Aug 04 '14 at 12:32
  • Agree :) Hm.. So if to switch to the new way of doing this, you advice to choose LINQ to XML ? Or there are another preferable options too? – Cristian E. Aug 04 '14 at 12:34
  • I'd definitely use LINQ to XML. – Jon Skeet Aug 04 '14 at 12:34

2 Answers2

4

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);
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

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();
}
Miroslav Siska
  • 401
  • 4
  • 15