代码之家  ›  专栏  ›  技术社区  ›  Jared Updike

使用XmlEralizer在C#中解析稍有偏差的XML

  •  2
  • Jared Updike  · 技术社区  · 16 年前

    标签周围 图像 条目)读取这些文件将是微不足道的——这不就是XML的意义吗?)

    基本上我被困在这里了。XML看起来像这样:

    <Series>
       <Metadata1>foo</Metadata1>
       <Metadata2>bar</Metadata2>
       ...
       <Image>...</Image>
       <Image>...</Image>
       ...
    </Series>
    

    (可以有任意数量的图像,但可能的元数据标签都是已知的)。我的代码看起来像这样:

    public class Image { ... }
    
    public class Series : List<Image>
    {
        public Series() { }
        public string Metadata1;
        public string Metadata2;
        ...
    }
    

    当我这样运行时:

                XmlSerializer xs = new XmlSerializer(typeof(Series));
                StreamReader sr = new StreamReader(path);
                Series series = (Series)xs.Deserialize(sr);
                sr.Close();
    

    public class Series    // // removed this : List<Image>
    {
        public Series() { }
        public string Metadata1;
        public string Metadata2;
        ...
    }
    

    然后在文件上运行阅读器,我得到一个完全填充了Metadata1/2/等的系列对象,但没有读取图像数据(显然)。

    List<Image> Images;
    3 回复  |  直到 16 年前
        1
  •  3
  •   Steve Guidi    16 年前

    the attributes

    [XmlElement]
    public class Image { ... }
    
    [XmlRoot(ElementName="Series")]
    public class Series
    {
            public Series() { }
    
            [XmlElement]
            public string Metadata1;
    
            [XmlElement]
            public string Metadata2;
    
            [XmlElement(ElementName="Image")]
            public Image[] Images;
    }
    

    编辑: 另一种选择是手工制作XML模式,以验证应用程序生成的文档,然后使用 XSD.exe

        2
  •  2
  •   Scott Dorman    16 年前

    您有一个硬件设备,它以某种方式生成您想要使用的XML数据。对我来说,使用简单的XmlDocument或XmlReader类而不是尝试遍历序列化程序是最简单的。

    public class Image { }
    
    public class Series
    {
       public string Metadata1;
       public string Metadata2;
       public List<Image> Images = new List<Image>();
    
       public void Load(string xml)
       {
          XmlDocument doc = new XmlDocument();
          doc.Load(xml);
    
          XmlNodeList images = doc.SelectNodes("Image");
          foreach (XmlNode image in images)
          {
             Images.Add(new Image(image.InnerText));
          }
    
          Metadata1 = GetMetadataValue(doc, "Metadata1");
          Metadata2 = GetMetadataValue(doc, "Metadata2");
       }
    
       private string GetMetadataValue(XmlDocument document, string nodeName)
       {
          string value = String.Empty;
          XmlNode metadataNode = document.SelectSingleNode(nodeName);
          if (metadataNode != null)
          {
             value = metaDataNode.InnerText;
          }
    
          return value;
       }
    }
    

    *这是未经测试/验证的代码,但它应该能让人理解这个想法。

        3
  •  1
  •   Thomas Levesque    16 年前

    我认为Steve的答案应该可行。我只是想补充一点,使用这种技术只能读取有限数量的元数据元素,因为它们没有常量名称。您可以做的是将它们读入XmlElements的集合中,以便稍后解析:

    [XmlRoot(ElementName="Series")]
    public class Series
    {
        public Series() { }
    
        [XmlAnyElement]
        XmlElement[] UnknownElements;
    
        private string[] _metadata;
        [XmlIgnore]
        public string[] Metadata
        {
            get
            {
                if (_metadata == null && UnknownElements != null)
                {
                    _metadata = UnknownElements
                                .Where(e => e.Name.StartsWith("Metadata")
                                .Select(e => e.InnerText)
                                .ToArray();
                }
                return _metadata;
            }
        }
    
        [XmlElement(ElementName="Image")]
        public Image[] Images;
    }