Как сериализовать Google Sitemap в C # с помощью XmlSerializer - PullRequest
4 голосов
/ 13 октября 2011

Я хочу сериализовать вот так

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

Но сгенерирован неверный результат.

Мой класс здесь

[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; }
}

Сериализатор здесь

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();
        }            

    }

Тогда результат здесь

<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"/>

Что не так в моем объявлении класса?

Другой ВОПРОС 2

Как я могу объявить вот так

<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>

мое объявление здесь

[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; }
    }

Это ошибка возврата

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.

Как я могу объявить то же имя корня "URL"?

Ответы [ 2 ]

8 голосов
/ 13 октября 2011

Вам нужно использовать правильное пространство имен:

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

вы можете убрать xmlns и xmlnsNews свойства - они делают что-то еще.Аналогично, любые данные в "" http://www.google.com/schemas/sitemap-news/0.9" должны быть помечены как таковые.То, является ли псевдоним пространства имен news, не имеет значения (это только псевдоним), но это можно контролировать с помощью XmlSerializerNamespaces, если хотите.Вам не нужно [Serializable].

Например, если каждый <url> должен находиться в пространстве имен "http://www.google.com/schemas/sitemap-news/0.9", и вы хотите использовать" http://www.sitemaps.org/schemas/sitemap/0.9" в качествеобщее пространство имен и "http://www.google.com/schemas/sitemap-news/0.9" с псевдонимом" новости ", затем:

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; }
}

. Это генерирует:

<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>

(я не проверял, что на самом деле пространства имен содержимогоare - это просто чтобы показать связь между пространствами имен в данных, пространствами имен в xml и псевдонимами пространств имен)


Повторное редактирование - что-то вроде:

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; }
}

который генерирует:

<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>
0 голосов
/ 20 июля 2012

Пожалуйста, используйте ниже полный код, который я сделал

Пожалуйста, смотрите ниже полный код

#region GoogleNewsSiteMap Class
[XmlRoot("urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
public class GoogleNewsSiteMap
{
    const string _newsSiteMapSchema = "http://www.google.com/schemas/sitemap-news/0.9";
    const string _newsSiteMapPrefix = "n";

    public void Create(string loc, string prioity, string language, string name, string genres, string publicationDate, string title)
    {
        NewsSiteMap news = new NewsSiteMap();
        news.Loc = loc;
        news.Priority = prioity;
        news.NewsSiteMapNews.Publication.Language = language;
        news.NewsSiteMapNews.Publication.Name = name;
        news.NewsSiteMapNews.Genres = genres;
        news.NewsSiteMapNews.PublicationDate = publicationDate;
        news.NewsSiteMapNews.Title = title;
        List.Add(news);
    }

    public string GetXMLString()
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;
        settings.IndentChars = ("    ");
        settings.Encoding = new UTF8Encoding(false);
        using (StringWriter str = new StringWriter())
        using (XmlWriter writer = XmlWriter.Create(str, settings))
        {
            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
            ns.Add(_newsSiteMapPrefix, _newsSiteMapSchema);
            XmlSerializer xser = new XmlSerializer(typeof(GoogleNewsSiteMap));
            xser.Serialize(writer, this, ns);
            return str.ToString();
        }
    }

    private List<NewsSiteMap> _list = null;
    [XmlElement("url")]
    public List<NewsSiteMap> List
    {
        get
        {
            if (_list == null)
            {
                _list = new List<NewsSiteMap>();
            }
            return _list;
        }
    }

    #region NewsSiteMap Class
    public class NewsSiteMap
    {
        private string _loc = string.Empty;
        private string _priority = string.Empty;
        private NewsSiteMap_News _newsSiteMap_News = null;

        [XmlElement("loc")]
        public string Loc
        {
            get { return _loc; } set { _loc = value; }
        }

        [XmlElement("priority")]
        public string Priority
        {
            get { return _priority; }  set { _priority = value; }
        }

        [XmlElement("news", Namespace = _newsSiteMapSchema)]
        public NewsSiteMap_News NewsSiteMapNews
        {
            get {
                if (_newsSiteMap_News == null)
                {
                    _newsSiteMap_News = new NewsSiteMap_News();
                }
                return _newsSiteMap_News; 
            }
            set { _newsSiteMap_News = value; }
        }

        #region NewsSiteMap_News Class
        public class NewsSiteMap_News
        {
            private NewsSiteMap_Publication _publication = null;
            private string _genres = string.Empty;
            private string _publicationDate = string.Empty;
            private string _title = string.Empty;
            private string _keywords = string.Empty;
            private string _stockTickers = string.Empty;

            [XmlElement("publication", Namespace = _newsSiteMapSchema)]
            public NewsSiteMap_Publication Publication
            {
                get
                {
                    if (_publication == null)
                    {
                        _publication = new NewsSiteMap_Publication();
                    }
                    return _publication;
                }
                set { _publication = value; }
            }

            [XmlElement("genres")]
            public string Genres
            {
                get { return _genres; }
                set { _genres = value; }
            }

            [XmlElement("publication_date")]
            public string PublicationDate
            {
                get
                {
                    try
                    {
                        return string.Format("{0:s}", Convert.ToDateTime(_publicationDate)) + string.Format("{0:zzz}", Convert.ToDateTime(_publicationDate));
                    }
                    catch (Exception ex)
                    {
                        return _publicationDate;
                    }
                }
                set { _publicationDate = value; }
            }

            public string Title
            {
                set { _title = value; }
            }

            [XmlElement("title")]
            public XmlCDataSection CTitle
            {
                get
                {
                    XmlDocument doc = new XmlDocument();
                    return doc.CreateCDataSection(_title);
                }
                set { _title = value.Value; }
            }

            [XmlElement("keywords")]
            public string Keywords
            {
                get { return _keywords; }  set { _keywords = value; }
            }

            [XmlElement("stock_tickers")]
            public string StockTickers
            {
                get { return _stockTickers; }  set { _stockTickers = value; }
            }

            #region NewsSiteMap_Publication Class
            public class NewsSiteMap_Publication
            {
                private string _name = string.Empty;
                private string _language = string.Empty;

                [XmlElement("name")]
                public string Name
                {
                    get { return _name; }
                    set { _name = value; }
                }

                [XmlElement("language")]
                public string Language
                {
                    get { return _language; }
                    set { _language = value; }
                }
            }
            #endregion NewsSiteMap_Publication Class
        }
        #endregion NewsSiteMap_News Class
    }
    #endregion NewsSiteMap Class
}
#endregion GoogleNewsSiteMap Class

Использование

Response.Clear();
Response.ContentType = "text/xml";
Response.ContentEncoding = System.Text.Encoding.UTF8;
GoogleNewsSiteMap googleNewsSiteMap = new GoogleNewsSiteMap();
googleNewsSiteMap.Create(/*put ur data*/);
Response.Write(googleNewsSiteMap.GetXMLString());
...