我称第三方Web服务返回大量XML数据(大约2mb),我想以比正常更受控制的方式将其反序列化为对象。这是xml:
<vehicle>
<vehicleManufacturer>
<type>1</type>
<name>A Make</name>
</vehicleManufacturer>
...
我知道我可以使用下面的代码来控制哪些元素被序列化到哪些属性,在这种情况下,Car Make对象包含两个属性,类型和名称。
<System.Xml.Serialization.XmlElement("vehicleManufacturer")> _
Public Property Make() As CarMake
但是,如果可能的话,我希望能够将名称字段反序列化为Make属性,或者甚至将整个元素及其内容序列化为文本。
<System.Xml.Serialization.XmlElement("vehicleManufacturer")> _
Public Property Make() As String
这是一个非常简化的例子,所以如果有任何资源可以帮助我,那就太棒了。
另一个例子:
<vehicle>
<warrantyDetail>
<warrantyBasicInformation buildStartdate="09/07/2013" warrantyStartDate="31/07/2013"/>
</warrantyDetail>
</vehicle>
我希望从保修基本信息中获取属性,而无需构建保修详细信息和warrantyBasicInformation对象。
请注意,这种事情通常是从WSDL生成的,但是,我没有提供一个,我没有XSD,trying to generate一个失败。我也知道我可以实现ISerializable并使用xml阅读器或linq,但同样,这可能会变成很多代码,也许很难维护。
答案 0 :(得分:2)
几周前我遇到类似的情况,你尝试使用的微软的xsd.exe无法生成合理的XML架构。我使用trang解决了这个问题,它完美地完成了这项工作。然后我使用xsd.exe自动生成包装类。
这可能无法完全回答您的问题,但使用xsd架构会让您的生活更轻松。
答案 1 :(得分:2)
我们一直在使用Xsd2Code来阅读xml文件。所有这些文件背后都有一个XSD,可以帮助生成(我认为XSD是你在没有大量手工编写代码的情况下解决问题的唯一方法,如果出现问题,请尝试自己编写,这并不难)
Xsd2Code使用Serialize和Deserialize方法生成一个代码文件,如下所示:
repositoryAsXml = settings.Serialize();
和
icn_database_v database;
if (!icn_database_v.Deserialize(xmlContents, out database, out exception))
{
throw exception;
}
答案 2 :(得分:1)
如果您不需要强类型,请考虑@Esen在XML class generator for serialization处使用以下自助滚动解决方案:
namespace Utility1
{
public static class XMLHelper
{
private enum XMLType
{
Element,
Attribute
}
public static string GenerateXMLClass(string xmlstring)
{
XmlDocument xd = new XmlDocument();
xd.LoadXml(xmlstring);
XmlNode rootNode = xd.DocumentElement;
var xmlClassCollection = new Dictionary<string, XMLClass>();
var xmlClass = new XMLClass();
xmlClassCollection.Add(rootNode.Name, xmlClass);
CollectAttributes(ref xmlClass, rootNode);
CollectElements(ref xmlClass, rootNode);
CollectChildClass(ref xmlClassCollection, rootNode);
var clsBuilder = new StringBuilder();
clsBuilder.AppendLine("[XmlRoot(\"" + rootNode.Name + "\")]");
foreach (var cls in xmlClassCollection)
{
clsBuilder.AppendLine("public class " + cls.Key);
clsBuilder.AppendLine("{");
foreach (var element in cls.Value.Elements)
{
if (XMLType.Element == element.XmlType)
clsBuilder.AppendLine("[XmlElement(\"" + element.Name + "\")]");
else
clsBuilder.AppendLine("[XmlAttribute(\"" + element.Name + "\")]");
clsBuilder.AppendLine("public " + element.Type + element.Name + "{get;set;}");
}
clsBuilder.AppendLine("}");
}
return clsBuilder.ToString();
}
private static void CollectAttributes(ref XMLClass xmlClass, XmlNode node)
{
if (null != node.Attributes)
{
foreach (XmlAttribute attr in node.Attributes)
{
if (null == xmlClass.Elements.SingleOrDefault(o => o.Name == attr.Name))
xmlClass.Elements.Add(new Element("string ", attr.Name, XMLType.Attribute));
}
}
}
private static bool IsEndElement(XmlNode node)
{
if ((null == node.Attributes || node.Attributes.Count <= 0) &&
(null == node.ChildNodes || !node.HasChildNodes || (node.ChildNodes.Count == 1 && node.ChildNodes[0].NodeType == XmlNodeType.Text)))
{
return true;
}
return false;
}
private static void CollectElements(ref XMLClass xmlClass, XmlNode node)
{
foreach (XmlNode childNode in node.ChildNodes)
{
if (null == xmlClass.Elements.SingleOrDefault(o => o.Name == childNode.Name))
{
var occurance = node.ChildNodes.Cast<XmlNode>().Where(o => o.Name == childNode.Name).Count();
var appender = " ";
if (occurance > 1)
appender = "[] ";
if(IsEndElement(childNode))
{
xmlClass.Elements.Add(new Element("string" + appender, childNode.Name, XMLType.Element));
}
else
{
xmlClass.Elements.Add(new Element(childNode.Name + appender, childNode.Name, XMLType.Element));
}
}
}
}
private static void CollectChildClass(ref Dictionary<string, XMLClass> xmlClsCollection, XmlNode node)
{
foreach (XmlNode childNode in node.ChildNodes)
{
if (!IsEndElement(childNode))
{
XMLClass xmlClass;
if (xmlClsCollection.ContainsKey(childNode.Name))
xmlClass = xmlClsCollection[childNode.Name];
else
{
xmlClass = new XMLClass();
xmlClsCollection.Add(childNode.Name, xmlClass);
}
CollectAttributes(ref xmlClass, childNode);
CollectElements(ref xmlClass, childNode);
CollectChildClass(ref xmlClsCollection, childNode);
}
}
}
private class XMLClass
{
public XMLClass()
{
Elements = new List<Element>();
}
public List<Element> Elements { get; set; }
}
private class Element
{
public Element(string type, string name, XMLType xmltype)
{
Type = type;
Name = name;
XmlType = xmltype;
}
public XMLType XmlType { get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
}
}
答案 3 :(得分:0)
我感觉这是一种代码味道,但它是我提出的最简单的方法。 (它假设节点将存在等,在这种情况下是可以的。)
Using tr As IO.TextReader = New IO.StringReader(strResult)
Using reader As System.Xml.XmlReader = System.Xml.XmlReader.Create(tr)
reader.MoveToContent()
While reader.Read
If reader.NodeType = Xml.XmlNodeType.Element Then
Select Case reader.Name
Case "warrantyDetail"
Dim xel As XElement = CType(XNode.ReadFrom(reader), Xml.Linq.XElement)
If xel IsNot Nothing Then
vi.RegCountry = xel.Element("country").Element("name").Value
vi.Reg = xel.Element("registration").Value
xel.Element("warrantyBasicInformation").Attribute("buildStartdate").Value
xel.Element("warrantyBasicInformation").Attribute("buildStartdate").Value
...
End If
Case ...
End Select
End If
End While
End Using
End Using