我有一个XML文档,使用反序列化,有没有办法将两个元素组合成一个对象?
XML示例:
$(document).ready(function(){
get = document.getElementsByClassName('imgs');
for(var i=0; i < get.length; i++){
oldH = get[i].naturalHeight;
oldW = get[i].naturalWidth;
divH = "500";
if(oldH > divH){
newH = divH;
calW = newH / oldH;
newW = calW * oldW;
get[i].height = newH;
get[i].width = newW;
console.log(newH, newW);
} else {
newH = oldH;
newW = oldW;
get[i].height = newH;
get[i].width = newW;
console.log(newH, newW);
}
}
});
我想创建一个列表(类型为Parameter),其中包含3和4项。
我尝试过使用XmlArrayItem,例如:
<Parameter1>3</Parameter1>
<Parameter2>4</Parameter2>
我尝试过使用XmlElements(但我无法弄清楚如何将它们组合起来):
[XmlArrayItem("Parameter1")]
[XmlArrayItem("Parameter2")]
[XmlArray]
public Parameter[] Parameters; // have also tried this as public List<Parameter> Parameters = new List<Parameter>();
如果不创建两个单独的列表并在以后合并它们,有没有办法做到这一点?
请注意,更改XML格式不是一种选择。
答案 0 :(得分:1)
您的XML具有包含choice元素的架构。 choice元素表示在您的情况下,一组固定的元素 - <Parameter1>
和<Parameter2>
将出现在XML中。 XmlSerializer
支持选择元素,如Choice Element Binding Support中所述:
如果个人选择元素&#39;类型与其名称不同,Xsd.exe仅将
XmlElementAttribute
属性应用于公共成员。如果它们仅按名称不同,则Xsd.exe另外应用XmlChoiceIdentifierAttribute
,并添加额外的逻辑以进行选择。
因此,您可以使用以下选项反序列化XML:
对Parameter
类进行子类化,并使用[XmlElementAttribute(String, Type)]
为每个元素名称指定不同的类型。因此,实例化的特定Parameter
子类将捕获XML元素名称。
即。你可以这样做:
public abstract class Parameter
{
[XmlText]
public string Value { get; set; } // Could be int if you prefer.
}
public class Parameter1 : Parameter
{
}
public class Parameter2 : Parameter
{
}
[XmlType("Root")]
public class RootObject
{
[XmlElement("Parameter1", typeof(Parameter1))]
[XmlElement("Parameter2", typeof(Parameter2))]
public Parameter[] Parameters { get; set; }
}
如果要使用相同的Parameter
类型反序列化<Parameter1>
和<Parameter2>
元素,则必须引入辅助XmlChoiceIdentifierAttribute
数组来捕获XML元素名称:
public class Parameter
{
[XmlText]
public string Value { get; set; }
}
[XmlType("Root")]
public class RootObject
{
[XmlElement("Parameter1", typeof(Parameter))]
[XmlElement("Parameter2", typeof(Parameter))]
[XmlChoiceIdentifier("ParametersElementName")]
public Parameter[] Parameters { get; set; }
[XmlIgnore]
public ParametersChoiceType[] ParametersElementName { get; set; }
}
[XmlType(IncludeInSchema = false)]
public enum ParametersChoiceType
{
Parameter1,
Parameter2,
}
反序列化后,ParametersElementName
数组将具有与Parameters
数组相同的条目数,其中的enum
值将指示每个参数实际遇到的XML元素名称。
作为选项2的变体,如果您不需要捕获XML元素名称并且只想反序列化值,则可以创建一个&#34; fake&#34;选择数组属性如下:
[XmlType("Root")]
public class RootObject
{
[XmlElement("Parameter1", typeof(Parameter))]
[XmlElement("Parameter2", typeof(Parameter))]
[XmlChoiceIdentifier("ParametersElementName")]
public Parameter[] Parameters { get; set; }
[XmlIgnore]
public ParametersChoiceType[] ParametersElementName
{
get
{
if (Parameters == null)
return null;
return Parameters.Select(p => ParametersChoiceType.Parameter1).ToArray();// Arbitrarily return ItemsChoiceType.Parameter1
}
set
{
// Do nothing - don't care.
}
}
}
XmlSerializer
要求您使用这两个选项之一。如果它无法按类型或项目选择标识符确定正确的元素名称,它将抛出InvalidOperationException
消息:
You need to add XmlChoiceIdentifierAttribute to the 'Parameters' member.
原型fiddle显示每个选项。
答案 1 :(得分:0)
如果你这样做会怎么样:
//get the xml doc
const string str = @"<root>
<Parameter1>3</Parameter1>
<Parameter2>4</Parameter2>
</root>";
var xml = new XmlDocument();
//load it
xml.LoadXml(str);
//get the nodes where the names contain the string parameter
var xnList = xml.SelectNodes("//*[contains(name(),'Parameter')]");
//create a list of parameters
var list = new List<Parameter>();
//populate the list with the value in the node's innertext
foreach (XmlNode xn in xnList)
{
list.Add(new Parameter{ Value = int.Parse(xn.InnerText) } );
}
foreach(var param in list)
Console.WriteLine(param.Value); //should print 3 and 4
我使用这个类作为例子:
class Parameter{
public int Value { get; set; }
}