简体   繁体   English

XmlSerializer按名称空间过滤

[英]XmlSerializer filter by namespace

I am trying to deserialise an RSS 2.0 feed and i would like to take into account some of the iTunes extensions, but not have to bake them directly into the main class. 我正在尝试反序列化RSS 2.0 feed,并且我想考虑一些iTunes扩展,但不必直接将它们烘焙到主类中。

With the XML deserialiser in C# would something like the following be possible? 使用C#中的XML反序列化器,可能会出现以下情况?

public class RssChannel
{
    [XmlElement("title")]
    public string Title { get; set; }

    [XmlElement("link")]
    public string Link { get; set; }

    ....

    [XmlElement(Namespace = "itunes")]
    public iTunesExtensions iTunes { get; set; }
}

public class iTunesExtensions 
{
    [XmlElement("category")]
    public string[] Categories { get; set; }
}

Which i am hoping would parse something like: 我希望可以解析如下内容:

<channel>
    <itunes:category text="Society & Culture"/>
    <itunes:category text="Society & Culture"/>
    <itunes:category text="Society & Culture"/>
</channel>

Is it possible to do something like this where it is more modular? 可以在模块化程度更高的地方做类似的事情吗? Or am i stuck baking it into the main class? 还是我坚持将其烘焙到主要班级?

bizzehdee, bizzehdee,

In order to set the first level to "", you would need to set it as the root and name of your class: 为了将第一级设置为“”,您需要将其设置为类的根目录和名称:

[XmlRoot("channel")]
public class channel

I will keep it as RssChannel, for the following examples. 对于以下示例,我将其保留为RssChannel。

I am assuming you intend to use more platforms than iTunes, so iTunes still has its own class. 我假设您打算使用比iTunes更多的平台,所以iTunes仍然有自己的类。 The way to do this, with less code, is to use a list instead of an array: 使用较少的代码即可完成此操作的方法是使用列表而不是数组:

public List<iTunes> iTunes;

Categories will have its own class, so that you can use categories with any platform. 类别将具有自己的类,因此您可以在任何平台上使用类别。 Notice the use of XmlAttribute. 注意XmlAttribute的使用。 This will include the name of the category in the same line: 这将在同一行中包含类别名称:

public class iTunes 
{
    public List<Category> Categories { get; set; }
}

public class Category
{
    [XmlAttribute("category")]
    public string category { get; set; }
}

You can use a static class to help you serialize and deserialize the data. 您可以使用静态类来帮助您序列化和反序列化数据。 Here are two methods in a static class that will help: 静态类中的以下两种方法会有所帮助:

// Save XML data.
public static void SaveData(ref RssChannel instance) {}

// Retrieve XML data.
public static RssChannel DeserializeData() {}

The best way to use these methods is to first get an instance of the RssChannel with the DeserializeData() method, like: 使用这些方法的最佳方法是首先使用DeserializeData()方法获取RssChannel的实例,例如:

RssChannel foo = StaticClassName.DeserializeData();

Make your changes to it, then save that instance by passing it as a reference to the SaveData() method, like: 对其进行更改,然后通过将其作为对SaveData()方法的引用进行传递来保存该实例,例如:

SaveData(ref foo);

Here is a full working example: 这是一个完整的工作示例:

public static class XML
{
    // Serializes the passed instance of RssChannel into XML file, and saves to runtime memory.
    public static void SaveData(ref RssChannel instance)
    {
        // Objects:
        StreamWriter sw = new StreamWriter("yourXmlFile.xml");
        XmlSerializer serializer = new XmlSerializer(typeof(RssChannel));

        // Save data.
        serializer.Serialize(sw, instance);
        sw.Close();
    }

    // Deserializes data from the XML file, and returns the instance.
    public static RssChannel DeserializeData()
    {
        // Objects:
        RssChannel channelData = new RssChannel();
        XmlSerializer serializer = new XmlSerializer(typeof(RssChannel));
        List<iTunes> iTunesList = new List<iTunes>();

        if (File.Exists("yourXmlFile.xml"))
        {
            FileStream stream = new FileStream("yourXmlFile.xml", FileMode.Open);

            // Deserialize data.
            channelData = (RssChannel)serializer.Deserialize(stream);
            stream.Close();

            // Add data from deserialized iTunes list to list instance.
            if (channelData.iTunesList != null)
                iTunesList = channelData.iTunesList;
        }

        // Add data to RootData object lists.
        channelData.iTunesList = iTunesList;

        return channelData;
    }
}

[XmlRoot("RssChannel")]
public class RssChannel
{
    [XmlAttribute("Title")]
    public string Title; // { get; set; }

    [XmlAttribute("Link")]
    public string Link; // { get; set; }

    public List<iTunes> iTunesList; // { get; set; }
}

public class iTunes 
{
    public List<Category> Categories; // { get; set; }
}

public class Category
{
    [XmlAttribute("category")]
    public string category; // { get; set; }
}

You can use the classes and static methods like this: 您可以使用这样的类和静态方法:

private void AnyMethod()
{
    // To get an instance of your RssChannel class with all the data:
    RssChannel rssChannel = XML.DeserializeData();

    // Do anything with the data. Example below:
    iTunes newITunes = new iTunes();
    List<Category> categoryList = new List<Category>();

    Category newCategory1 = new Category(); // Create new categories.
    newCategory1.category = "Allegro";
    categoryList.Add(newCategory1);

    Category newCategory2 = new Category();
    newCategory2.category = "Prestissimo";
    categoryList.Add(newCategory2);

    newITunes.Categories = categoryList; // Add the categories to list.

    rssChannel.iTunesList.Add(newITunes); // Add that list to iTunes list.

    // Now, to save the data, pass a reference to the instance we just worked on:
    XML.SaveData(ref rssChannel);
}

This will produce a file that looks like: 这将产生一个如下文件:

<?xml version="1.0" encoding="utf-8"?>
<RssChannel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <iTunesList>
    <iTunes>
      <Categories>
        <Category category="Allegro" />
        <Category category="Prestissimo" />
      </Categories>
    </iTunes>
  </iTunesList>
</RssChannel>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM