#c# #xml-serialization #xml-sitemap
#c# #xml-сериализация #xml-карта сайта
Вопрос:
Я хочу сериализовать следующим образом
<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»?
Комментарии:
1. Повторите редактирование: вы не можете иметь оба
gNormalUrl
иgNewsUrl
вызывать одно и то же в одном и том же пространстве имен, поскольку у него не было бы никакого способа выяснить, что создавать во время десериализации. В принципе, это запрещено. Используйте либо разные имена, либо один конкретный тип.2. Я попытаюсь показать класс, который ведет себя так, как вы хотите… 2 минуты…
Ответ №1:
Вам нужно использовать правильное пространство имен:
[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>
(Я не проверял, каковы фактические пространства имен содержимого — это просто для того, чтобы показать взаимосвязь между пространствами имен в данных, пространствами имен в 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>
Комментарии:
1. Спасибо вам за ответ. Но у меня есть еще один вопрос. Пожалуйста, ознакомьтесь с моими вопросами в нижней части
Ответ №2:
Пожалуйста, используйте ниже полный код, созданный мной
Пожалуйста, смотрите Ниже полный код
#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());