Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serialize google sitemap in c# using XmlSerializer

I want to serialize like this

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">
</urlset>

But wrong result generated.

My class is here

[Serializable]
[XmlRoot("urlset")]    
public class GoogleSiteMap
{        
    public GoogleSiteMap() {
        xmlns = "http://www.sitemaps.org/schemas/sitemap/0.9";
        xmlnsNews = "http://www.google.com/schemas/sitemap-news/0.9";
        Urls = new List<gUrlBase>();
    }

    [XmlAttribute]
    public string xmlns { get; set; }

    [XmlAttribute("news",Namespace="xmlns")]
    public string xmlnsNews { get; set; }

    [XmlElement("url")]
    public List<gUrlBase> Urls { get; set; }
}

Serializer is here

public static void GenerateGoogle(GoogleSiteMap smap,string filePath) {

        XmlSerializer ser = new XmlSerializer(typeof(GoogleSiteMap));
        using (FileStream fs = new FileStream(filePath, FileMode.Create))
        {
            ser.Serialize(fs, smap);
            fs.Close();
        }            

    }

Then result is here

<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:d1p1="xmlns" d1p1:news="http://www.google.com/schemas/sitemap-news/0.9"/>

What's wrong on my class declaration?

Another QUESTION 2

How can i declare like this

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">
    <url>
        <loc>http://www.example.org/business/article55.html</loc>
        <news:news></news:news>
    </url>
    <url>
        <loc>http://www.example.org/business/page1.html</loc>
        <lastmod>2010-10-10</lastmod>
        <changefreq>weekly</changefreq>
    </url>
</urlset>

my declaration is here

[XmlRoot("urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
    public class GoogleSiteMap
    {
        public GoogleSiteMap()
        {
            Urls = new List<gUrlBase>();
        }

        //[XmlElement("url")]
        [XmlElement("url",Type = typeof(gNormalUrl))]
        [XmlElement("url",Type = typeof(gNewsUrl))]
        public List<gUrlBase> Urls { get; set; }
    }

This is return error

The XML element 'url' from namespace 'http://www.sitemaps.org/schemas/sitemap/0.9' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.

How can i declare Same root name "url"?

like image 370
ebattulga Avatar asked Feb 22 '23 17:02

ebattulga


1 Answers

You need to use the right namespace:

[XmlRoot("urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]

you can take away xmlns and xmlnsNews properties - they do something else. Likewise, any data in ""http://www.google.com/schemas/sitemap-news/0.9" will need to be marked as such. Whether the namespace alias is news is irrelevant (it is only an alias), but that can be controlled via XmlSerializerNamespaces if you like. You do not need [Serializable].

For example, if each <url> needs to be in the "http://www.google.com/schemas/sitemap-news/0.9" namespace, and you want to use "http://www.sitemaps.org/schemas/sitemap/0.9" as the overall namespace and "http://www.google.com/schemas/sitemap-news/0.9" aliased as "news", then:

static class Program
{
    static void Main()
    {
        var ns = new XmlSerializerNamespaces();
        ns.Add("", "http://www.sitemaps.org/schemas/sitemap/0.9");
        ns.Add("news", "http://www.google.com/schemas/sitemap-news/0.9");
        var ser = new XmlSerializer(typeof (GoogleSiteMap));
        var obj = new GoogleSiteMap {Urls = new List<string> {"abc", "def", "ghi"}};
        ser.Serialize(Console.Out, obj, ns);
    }
}

[XmlRoot("urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
public class GoogleSiteMap
{

    [XmlElement("url", Namespace = "http://www.google.com/schemas/sitemap-news/0.9")]
    public List<string> Urls { get; set; }
}

This generates:

<urlset
     xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"
     xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <news:url>abc</news:url>
  <news:url>def</news:url>
  <news:url>ghi</news:url>
</urlset>

(I haven't checked what the actual content namespaces are - this is just to show the relationship between namespaces in the data, namespaces in the xml, and namespace-aliases)


Re your edit - something like:

static class Program
{
    static void Main()
    {
        var ns = new XmlSerializerNamespaces();
        ns.Add("", "http://www.sitemaps.org/schemas/sitemap/0.9");
        ns.Add("news", "http://www.google.com/schemas/sitemap-news/0.9");
        var ser = new XmlSerializer(typeof (GoogleSiteMap));
        var obj = new GoogleSiteMap {Urls = {
            new SiteUrl { Location = "http://www.example.org/business/article55.html", News = ""},
            new SiteUrl { Location = "http://www.example.org/business/page1.html", LastModified = new DateTime(2010,10,10),
            ChangeFrequency = "weekly"}
        }};
        ser.Serialize(Console.Out, obj, ns);
    }
}

[XmlRoot("urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
public class GoogleSiteMap
{
    private readonly List<SiteUrl> urls = new List<SiteUrl>();
    [XmlElement("url")]
    public List<SiteUrl> Urls { get { return urls; } }
}

public class SiteUrl
{
    [XmlElement("loc")]
    public string Location { get; set; }
    [XmlElement("news", Namespace = "http://www.google.com/schemas/sitemap-news/0.9")]
    public string News { get; set; }
    [XmlElement("lastmod")]
    public DateTime? LastModified { get; set; }
    [XmlElement("changefreq")]
    public string ChangeFrequency { get; set; }

    public bool ShouldSerializeLastModified() { return LastModified.HasValue; }
}

which generates:

<urlset xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"
        xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>http://www.example.org/business/article55.html</loc>
    <news:news />
  </url>
  <url>
    <loc>http://www.example.org/business/page1.html</loc>
    <lastmod>2010-10-10T00:00:00</lastmod>
    <changefreq>weekly</changefreq>
  </url>
</urlset>
like image 57
Marc Gravell Avatar answered Mar 08 '23 06:03

Marc Gravell