我目前遇到了C#中xml序列化的问题。
我的程序中有一个像这样的XML结构代表树:
<FlatNodeTree>
<Node>
<Level>1</Level>
<Name>Element 0</Name>
<Guid>AAA</Guid>
<NodeType>XElt</NodeType>
<GuidParent />
</Node>
<Node>
<Level>1</Level>
<Name>Block 1</Name>
<Guid>BBB</Guid>
<NodeType>XBlock</NodeType>
<GuidParent />
</Node>
<Node>
<Level>2</Level>
<Name>Element 1</Name>
<Guid>CCC</Guid>
<NodeType>XElt</NodeType>
<GuidParent>BBB</GuidParent>
</Node>
<Node>
<Level>1</Level>
<Name>Element 2</Name>
<Guid>DDD</Guid>
<NodeType>XElt</NodeType>
<GuidParent />
</Node>
</FlatNodeTree>
你可以看到有节点(XBlock)和叶子(XElt),以及水平对象&gt; 1由Guid附加到父节点。
我希望将它保存在这样的xml结构中(它非常简单,但你明白了):
<Article>
<Elt>Element 0</Elt>
<Block name='Block 1'>
<Elt>Element 1</Elt>
</Block>
<Elt>Element 2</Elt>
</Article>
我在C#中用来序列化的类看起来像这样:
[Serializable]
public class XArticle
{
public XArticle()
{
Blocks = new List<XBlock>();
Elts = new List<XElt>();
}
[XmlElement("block")]
public List<XBlock> Blocks { get; set; }
[XmlElement("elt")]
public List<XElt> Elts { get; set; }
/*Plenty of other stuff*/
}
我也有XBlock和XElt类。 XBlock类有一个innerBlocks属性,它只是一个允许多个级别的List。
我的问题在于,当我尝试创建我的XArticle时,Blocks和Elts存储在2个单独的列表中,因此当我尝试序列化它时,它会逐个序列化列表并且我完全失去了块和elts的顺序如果它们是混合的。
以下是我获取的XML的示例,而不是之前发布的XML:
<Article>
<Block name='Block 1'>
<Elt>Element 1</Elt>
</Block>
<Elt>Element 0</Elt>
<Elt>Element 2</Elt>
</Article>
您可以看到它首先序列化所有块,然后序列化每个节点内的所有元素。
我对序列化知之甚少,我想知道是否有xml指令或可以解决此问题的东西。
我想到的解决方案是在创建无组织的xml后重新排序Blocks和Elts标签,但也许有更好的解决方案。
PS:我使用System.Xml.Serialization.XmlSerializer
。
PPS:告诉我你是否需要看到将xpath数据转换为X-class的函数。
答案 0 :(得分:0)
如果要混合序列化列表中的类型,则应创建一个具有2个装饰属性的属性,如下所示:
[Serializable]
public class XArticle
{
[XmlElement(Type = typeof(XBlock), ElementName = "Block")]
[XmlElement(Type = typeof(XElt), ElementName = "Elt")]
public List<object> Elements { get; set; }
}
如果您使用以下内容填充元素:
Elements = new List<object> { new XElt { Text = "Element 0" }, new XBlock { Elt = new XElt { Text = "Element 1 " }, Name = "Block 1" }, new XElt { Text = "Element 2 " } };
它产生xml:
<?xml version="1.0"?>
<XArticle xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Elt>Element 0</Elt>
<Block name="Block 1">
<Elt>Element 1 </Elt>
</Block>
<Elt>Element 2 </Elt>
</XArticle>
编辑: 如果必须保留Blocks和Elts属性,则可以执行以下操作:
[Serializable]
public class XArticle
{
[XmlIgnore]
public List<XBlock> Blocks { get; set; }
[XmlIgnore]
public List<XElt> Elts { get; set; }
[XmlElement(Type = typeof(XBlock), ElementName = "Block")]
[XmlElement(Type = typeof(XElt), ElementName = "Elt")]
public List<object> Elements
{
get
{
return Blocks.Select(b => new KeyValuePair<string, object>(b.Elt.Text, b))
.Concat(Elts.Select(e => new KeyValuePair<string, object>(e.Text, e)))
.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value).ToList();
}
set { }
}
这将创建一个按Text属性排序的列表。 您可以替换您希望订购的任何其他字段。
答案 1 :(得分:0)
非常感谢你的帮助,我能够解决我的问题!
对于其他人来说,它可能有所帮助,我设法通过创建2个递归函数重新排序我的最终xml:
第一个,在反序列化之后转换2个列表中的List<object> Elements
(List<XBlock> Blocks
和List<XElt> Elts
,请记住,它们在程序中被使用并且必须被馈送)。
第二个,在序列化之前将2个列表(Blocks和Elts)合并为一个列表(Elements)。