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>
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.
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With