Question

I've got the following classes for my sitemap generation:

public class SitemapItem
{
    public SitemapItem(string url)
    {
        this.Url = url;
        this.AlternateLinks = new List<SiteMapAlternateLink>();
    }

    public string Url { get; set; }

    public DateTime? LastModified { get; set; }

    public ChangeFrequency? ChangeFrequency { get; set; }

    public float? Priority { get; set; }

    public List<SiteMapAlternateLink> AlternateLinks { get; set; }
}

And:

public class SiteMapAlternateLink
{
    public SiteMapAlternateLink(string url, string language)
    {
        this.Url = url;
        this.Language = language;
    }

    public string Url { get; set; }

    public string Language { get; set; }
}

Now in my controller I fill a list of SitemapItems and return it from the controller with the following code:

public class XmlSitemapResult : ActionResult
{
    private XNamespace nsSitemap = "http://www.sitemaps.org/schemas/sitemap/0.9";
    private XNamespace nsXhtml = "http://www.w3.org/1999/xhtml";

    private IEnumerable<SitemapItem> _items;

    public XmlSitemapResult(IEnumerable<SitemapItem> items)
    {
        _items = items;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        string encoding = context.HttpContext.Response.ContentEncoding.WebName;
        XDocument sitemap = new XDocument(new XDeclaration("1.0", encoding, "yes"),
             new XElement(nsSitemap + "urlset", new XAttribute(XNamespace.Xmlns + "xhtml", nsXhtml),
                  from item in _items
                  select CreateItemElement(item)
                  )
             );

        context.HttpContext.Response.ContentType = "application/xml";
        context.HttpContext.Response.Charset = encoding;
        context.HttpContext.Response.Flush();
        context.HttpContext.Response.Write(sitemap.Declaration + sitemap.ToString());
    }

    private XElement CreateItemElement(SitemapItem item)
    {
        XElement itemElement = new XElement(nsSitemap + "url", new XElement(nsSitemap + "loc", item.Url.ToLower()));

        if (item.LastModified.HasValue)
            itemElement.Add(new XElement(nsSitemap + "lastmod", item.LastModified.Value.ToString("yyyy-MM-dd")));

        if (item.ChangeFrequency.HasValue)
            itemElement.Add(new XElement(nsSitemap + "changefreq", item.ChangeFrequency.Value.ToString().ToLower()));

        if (item.Priority.HasValue)
            itemElement.Add(new XElement(nsSitemap + "priority", item.Priority.Value.ToString(CultureInfo.InvariantCulture)));

        foreach (var alternateLink in item.AlternateLinks)
        {
            itemElement.Add(new XElement(nsXhtml + "link", 
                new XAttribute("rel", "alternate"),
                new XAttribute("hreflang", alternateLink.Language),
                new XAttribute("href", alternateLink.Url)));
        }

        return itemElement;
    }
}

Now the problem is that in my browser I won't see the XML as XML. I'll just see text which doesn't get viewed with the standard XML Viewer. This happens in all browsers and it seems it happend from the moment I added the xhtml schema.

Hopefully somebody sees the problem, thanks in advance!

EDIT: If I remove everything that has to do with xhtml the browser DOES show it as a xml. Any ideas?

EDIT2: The html:

 <urlset xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>http://localhost:11149/en</loc>
    <changefreq>hourly</changefreq>
    <priority>0.6</priority>
    <xhtml:link rel="alternate" hreflang="en" href="http://localhost:11149/en"/>
    <xhtml:link rel="alternate" hreflang="nl" href="http://localhost:11149/nl"/>
  </url>
  <url>
    <loc>http://localhost:11149/en/buyandsell</loc>
    <changefreq>weekly</changefreq>
    <priority>1</priority>
    <xhtml:link rel="alternate" hreflang="en" href="http://localhost:11149/en/BuyAndSell"/>
    <xhtml:link rel="alternate" hreflang="nl" href="http://localhost:11149/nl/BuyAndSell"/>
  </url>
  <url>
    <loc>http://localhost:11149/en/partner</loc>
    <changefreq>weekly</changefreq>
    <priority>0.5</priority>
    <xhtml:link rel="alternate" hreflang="en" href="http://localhost:11149/en/Partner"/>
    <xhtml:link rel="alternate" hreflang="nl" href="http://localhost:11149/nl/Partner"/>
  </url>
  <url>
    <loc>http://localhost:11149/en/news</loc>
    <lastmod>2013-12-06</lastmod>
    <changefreq>daily</changefreq>
    <priority>0.6</priority>
    <xhtml:link rel="alternate" hreflang="en" href="http://localhost:11149/en/News"/>
    <xhtml:link rel="alternate" hreflang="nl" href="http://localhost:11149/nl/News"/>
  </url>
</urlset>
Was it helpful?

Solution

Here's what we do to generate the sitemap for autoquoter.com. See http://www.autoquoter.com/aq/sitemap.xml

        var sitemap = new XDocument(
            new XDeclaration("1.0", "utf-8", "yes"),
            new XProcessingInstruction("xml-stylesheet",
                "type=\"text/xsl\" href=\"" + Url.AbsoluteAction("SitemapXsl", "Default") + "\""),
            new XElement(ns + "urlset",
                new XAttribute(XNamespace.Xmlns + "sitemap", ns),
                new XAttribute(XNamespace.Xmlns + "xhtml", xhtml), 
                nodeList));

        Response.AddHeader("X-Robots-Tag","noindex");
        return Content(sitemap.Declaration+"\r\n"+sitemap, "text/xml");

We also use an xsl stylesheet to transform the sitemap. This helps with browsers that don't provide a decent formatter automatically. See http://www.autoquoter.com/aq/en/Default/SitemapXsl for the stylesheet that we are using.

OTHER TIPS

EDIT 1:

It seems that you may lose some of the xml specific header files:

Check this link out

This might also be a valid example on how to create an xml site map:

Sitemap xml for google Another example
OPTION1 Try this code out(taken from here):

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class Sitemap : IHttpHandler
    {
        private const string NAMESPACE = "http://www.sitemaps.org/schemas/sitemap/0.9";

        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/xml";
            XmlDocument sitemapDocument = GetSitemapDocument();
            context.Response.Write(sitemapDocument.InnerXml);
        }

        #region Build sitemap document methods
        private XmlDocument GetSitemapDocument()
        {
            XmlDocument sitemapDocument = new XmlDocument();
            sitemapDocument.PreserveWhitespace = true;

            XmlDeclaration xmlDeclaration = 
                sitemapDocument.CreateXmlDeclaration("1.0", "UTF-8", string.Empty);
            sitemapDocument.AppendChild(xmlDeclaration);

            XmlElement urlset = sitemapDocument.CreateElement("urlset", NAMESPACE);
            sitemapDocument.AppendChild(urlset);

            List<SitemapPage> urls = GetSitemapPages();

            foreach (SitemapPage sitemapPage in urls)
            {
                XmlElement url = CreateUrlElement(sitemapDocument, sitemapPage);
                urlset.AppendChild(url);
            }
            return sitemapDocument;
        }

        private XmlElement CreateUrlElement(XmlDocument sitemapDocument, 
            SitemapPage sitemapPage)
        {
            XmlElement url = sitemapDocument.CreateElement("url", NAMESPACE);

            XmlElement loc = CreateElementWithText(sitemapDocument, "loc", 
                sitemapPage.Location);
            url.AppendChild(loc);

            if (sitemapPage.LastModificationDate.HasValue)
            {
                //lastmod must be a string that comforms to the W3C Datetime format
                string lastModValue = sitemapPage.LastModificationDate.Value.ToString(
                    "yyyy'-'MM'-'dd'T'HH':'mm':'ssK");
                XmlElement lastmod = CreateElementWithText(
                    sitemapDocument, "lastmod", lastModValue);
                url.AppendChild(lastmod);
            }

            if (!string.IsNullOrEmpty(sitemapPage.ChangeFrequency))
            {
                XmlElement changefreq = CreateElementWithText(sitemapDocument, 
                    "changefreq", sitemapPage.ChangeFrequency);
                url.AppendChild(changefreq);
            }

            if (sitemapPage.Priority.HasValue)
            {
                XmlElement priority = CreateElementWithText(sitemapDocument,
                    "priority", sitemapPage.Priority.Value.ToString(
                        CultureInfo.CreateSpecificCulture("en-US")));
                url.AppendChild(priority);
            }

            return url;
        }

        private XmlElement CreateElementWithText(
            XmlDocument document, string elementName, string text)
        {
            XmlElement element = document.CreateElement(elementName, NAMESPACE);

            XmlText elementValue = document.CreateTextNode(text);
            element.AppendChild(elementValue);

            return element;
        }
        #endregion

        private List<SitemapPage> GetSitemapPages()
        {
            List<SitemapPage> sitemapPages = new List<SitemapPage>();

            //Example implementation
            sitemapPages.Add(new SitemapPage("http://www.mydomain.com") 
                { ChangeFrequency = "daily", LastModificationDate = DateTime.Now, Priority = 1f });
            sitemapPages.Add(new SitemapPage("http://www.mydomain.com/aPage.aspx") 
                { ChangeFrequency = "daily", LastModificationDate = DateTime.Now, Priority = 0.8f });

            return sitemapPages;
        }

        private class SitemapPage
        {
            public SitemapPage(string location)
            {
                Location = location;
            }

            public string Location { get; private set; }
            public DateTime? LastModificationDate { get; set; }
            public string ChangeFrequency { get; set; }
            public float? Priority { get; set; }
        }

        public bool IsReusable
        {
            get
            {
                return true;
            }
        }
    }

OPTION2: According to MSDN this is a valid sitemap: sitemap MSDN.

Check this output out:

<siteMap>
  <siteMapNode title="Home" description="Home" url="~/default.aspx">
    <siteMapNode title="Products" description="Our products"
      url="~/Products.aspx">
      <siteMapNode title="Hardware" description="Hardware choices"
        url="~/Hardware.aspx" />
      <siteMapNode title="Software" description="Software choices"
        url="~/Software.aspx" />
    </siteMapNode>
    <siteMapNode title="Services" description="Services we offer"
        url="~/Services.aspx">
        <siteMapNode title="Training" description="Training classes"
          url="~/Training.aspx" />
        <siteMapNode title="Consulting" description="Consulting services" 
          url="~/Consulting.aspx" />
        <siteMapNode title="Support" description="Supports plans" 
          url="~/Support.aspx" />
    </siteMapNode>
  </siteMapNode>
</siteMap>

Maybe you should try change your code:

public class XmlSitemapResult : ActionResult
{
    private XNamespace nsSitemap = "http://www.sitemaps.org/schemas/sitemap/0.9";
    private XNamespace nsXhtml = "http://www.w3.org/1999/xhtml";

    private IEnumerable<SitemapItem> _items;

    public XmlSitemapResult(IEnumerable<SitemapItem> items)
    {
        _items = items;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        string encoding = context.HttpContext.Response.ContentEncoding.WebName;
        XDocument sitemap = new XDocument(new XDeclaration("1.0", encoding, "yes"),
             new XElement(nsSitemap + "siteMap", new XAttribute(XNamespace.Xmlns + "xhtml", nsXhtml),
                  from item in _items
                  select CreateItemElement(item)
                  )
             );

        context.HttpContext.Response.ContentType = "application/xml";
        context.HttpContext.Response.Charset = encoding;
        context.HttpContext.Response.Flush();
        context.HttpContext.Response.Write(sitemap.Declaration + sitemap.ToString());
    }

    private XElement CreateItemElement(SitemapItem item)
    {
        XElement itemElement = new XElement(nsSitemap + "siteMapNode", new XElement(nsSitemap + "loc", item.Url.ToLower()));

        if (item.LastModified.HasValue)
            itemElement.Add(new XElement(nsSitemap + "lastmod", item.LastModified.Value.ToString("yyyy-MM-dd")));

        if (item.ChangeFrequency.HasValue)
            itemElement.Add(new XElement(nsSitemap + "changefreq", item.ChangeFrequency.Value.ToString().ToLower()));

        if (item.Priority.HasValue)
            itemElement.Add(new XElement(nsSitemap + "priority", item.Priority.Value.ToString(CultureInfo.InvariantCulture)));

        foreach (var alternateLink in item.AlternateLinks)
        {
            itemElement.Add(new XElement(nsXhtml + "link", 
                new XAttribute("rel", "alternate"),
                new XAttribute("hreflang", alternateLink.Language),
                new XAttribute("href", alternateLink.Url)));
        }

        return itemElement;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top