将 XmlAttribute 解析为复杂类型

Posted

技术标签:

【中文标题】将 XmlAttribute 解析为复杂类型【英文标题】:Parsing XmlAttribute as complex type 【发布时间】:2014-09-24 22:16:20 【问题描述】:

我正在尝试创建 SVG 格式的对象模型。所以,由于它是 XML,我使用的是 XmlSerializer。但我有一个问题。有一些名为“样式”的 xml 属性。它看起来像复杂类型,但表示为字符串。有这个属性的例子:

style="fill:none;stroke:#00ff00;stroke-width:8.7489996;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:8.74900006"

如您所见,有“fill”、“stroke”、“stroke-width”等属性。 我写的课

public class SvgStyle

    public string FillColor  get; set; 
    public string StrokeColor  get; set; 
    public float StrokeWidth  get; set; 
    public int StrokeMiterlimit  get; set; 
    public float StrokeOpacity  get; set; 
    public float StrokeDashoffset  get; set; 
    public string StrokeDasharray  get; set; 

和另一个班级

public abstract class SvgGraphicElement

    [XmlAttribute("style")]
    public SvgStyle Style  get; set; 

我得到的只是例外

无法序列化 Svg.SvgStyle 类型的成员“样式”。 XmlAttribute/XmlText 不能用于编码复杂类型。

我尝试使用 IXmlSerializable 接口实现和 OnSerializing/OnDeserializing 方法,但我得到的只是另一个例外。 有没有办法将此字符串反序列化到我的班级? 谢谢。

【问题讨论】:

【参考方案1】:

我相信你需要在你的 SVGStyle 类上实现 IXmlSerializable 接口

http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx

刚刚读到您已经尝试过;对不起。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Xml.Serialization;

namespace XmlTypes

  public class SvgStyle : IXmlSerializable
  

    private const string fillColorKey = "fill";
    private const string strokeColorKey ="stroke";
    private const string strokeWidthKey = "stroke-width";
    private const string strokeMiterLimitKey = "stroke-miterlimit";
    private const string strokeOpacityKey ="stroke-opacity";
    private const string strokeDashArrayKey="stroke-dasharray";
    private const string strokeDashOffsetKey = "stroke-dashoffset";

    [XmlAttribute]
    public String Style  get; set; 
    public string FillColor  get; set; 
    public string StrokeColor  get; set; 
    public float StrokeWidth  get; set; 
    public int StrokeMiterlimit  get; set; 
    public float StrokeOpacity  get; set; 
    public float StrokeDashoffset  get; set; 
    public string StrokeDasharray  get; set; 


    public System.Xml.Schema.XmlSchema GetSchema()
    
      return null;
    

    public void ReadXml(System.Xml.XmlReader reader)
    
      reader.MoveToContent();
      Style = reader.GetAttribute("style");
      Dictionary<string, string> lookupTable = ParseAttribute(Style);

      FillColor = lookupTable[fillColorKey];
      StrokeColor = lookupTable[strokeColorKey];

      float strokeWidthFloatValue=0; 
      float.TryParse(lookupTable[strokeWidthKey] , out strokeWidthFloatValue) ;
      StrokeWidth = strokeWidthFloatValue;

      int strokeMiterLimitInt = 0;
      Int32.TryParse(lookupTable[strokeMiterLimitKey] , out strokeMiterLimitInt);
      StrokeMiterlimit = strokeMiterLimitInt;

      int strokeOpacityInt = 0;
      Int32.TryParse(lookupTable[strokeMiterLimitKey], out strokeOpacityInt);
      StrokeOpacity = strokeOpacityInt;

      int strokeDashOffsetInt = 0;
      Int32.TryParse(lookupTable[strokeMiterLimitKey], out strokeDashOffsetInt);
      StrokeDashoffset = strokeDashOffsetInt;

      StrokeDasharray = lookupTable[strokeDashArrayKey];


      Boolean isEmptyElement = reader.IsEmptyElement; // (1)
      reader.ReadStartElement();

    

    public void WriteXml(System.Xml.XmlWriter writer)
    
      writer.WriteAttributeString("style", Style);

    
    private Dictionary<string, string> ParseAttribute(string attribute)
    
      string[] arr = attribute.Split(';');
      Dictionary<string, string> dic = new Dictionary<string, string>();
      for(int i = 0; i < arr.Length; i++)
      
        string[] arrItem = arr[i].Split(':');
        dic.Add(arrItem[0], arrItem[1]);
      
      return dic;
        
  






 [TestMethod]
    public void TestMethod1()
    
      string xml = @"<SvgStyle style='fill:none;stroke:#00ff00;stroke-width:8.7489996;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:8.74900006'></SvgStyle>";

      XmlSerializer x = new XmlSerializer(typeof(SvgStyle));
      SvgStyle myTest = (SvgStyle)x.Deserialize(new StringReader(xml));

    

【讨论】:

实现 IXmlSerializable 接口给了我另一个异常“无法序列化 Svg.SvgStyle 类型的成员 'Style'。XmlAttribute/XmlText 不能用于编码实现 IXmlSerializable 的类型”。那么,您能否详细说明我应该如何实现它?我在类上设置了所有属性,它的属性就像这个例子中的link。 在您的示例中,您合并了两个不同的实体,在我的例子中是 SvgGraphicElement 和 SvgStyle。也许这是我的错误,但是“样式”是 SvgGraphicElement 的属性,并且没有 SvgStyle 元素。目前看来我需要为 SvgGraphicElement 类实现 IXmlSerializable 接口,但不是 SvgStyle。 可以提供xml吗? 这是示例 xml:&lt;svg id="svg2"&gt; &lt;defs id="defs4" /&gt; &lt;metadata id="metadata7"&gt; &lt;rdf:RDF&gt; &lt;cc:Work rdf:about=""&gt; &lt;dc:format&gt;image/svg+xml&lt;/dc:format&gt; &lt;dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /&gt; &lt;dc:title&gt;&lt;/dc:title&gt; &lt;/cc:Work&gt; &lt;/rdf:RDF&gt; &lt;/metadata&gt; &lt;g id="layer1"&gt; &lt;rect width="497" height="177" id="rect2985" style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:54;stroke-miterlimit:51;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:50" /&gt; &lt;/g&gt; &lt;/svg&gt;

以上是关于将 XmlAttribute 解析为复杂类型的主要内容,如果未能解决你的问题,请参考以下文章

XML 反序列化:在单个属性上使用 XmlAttribute 和 XmlText

使用 powershell 将嵌套的复杂 XML 解析为 CSV

XMLAttribute 不工作

在 C# visual2005 中使用 XmlAttribute() 检索

在Java中的xmlElement上添加xmlAttribute

TBXML 将复杂的 xml 解析为数组