如何使用 XmlSerializer 属性分析此 XML
本文关键字:XML 属性 何使用 XmlSerializer | 更新日期: 2023-09-27 18:21:35
我们需要使用一个"Web服务"来传达极其丑陋的XML。它不是由我们开发的,并且没有机会使其开发人员理解正确的XML。
仅供参考,此Web服务还接受HTTP GET URL参数(而不是请求正文(中的相同类型的XML - 开发它的人不明白为什么这是一种不好的做法。
那么,映射 XML 的最快方法是什么,如下所示:
<foo id="document">
<foo id="customer">
<bar name="firstname" value="Joe"/>
<bar name="lastname" value="Smith"/>
<foo id="address">
<bar name="city" value="New York"/>
<bar name="country" value="USA"/>
</foo>
</foo>
<bar name="somemoredata1" value="123"/>
<bar name="somemoredata2" value="abc"/>
</foo>
进入这样的类:
public class Document
{
public Customer Customer { get; set; }
public int SomeMoreData1 { get; set; }
public string SomeMoreData2 { get; set; }
}
public class Customer
{
public Address Address { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Address
{
public string City { get; set; }
public string Country { get; set; }
}
使用例如。XML 序列化程序属性或需要尽可能少的样板代码的任何其他方式。
我编造了foo
和bar
元素名称,但我需要解析的 XML 结构基于完全相同的约定。
我当然可以在这些类中手动实现IXmlSerializable
,或者只是制作Foo
和Bar
类并将其与XmlSerializer
一起使用,但这些选项似乎都不是一个好的解决方案。
提前感谢您的回答!
你不能用XML序列化程序属性做到这一点:只是没有办法让它从指定的属性中取出字段名称。您必须手动反序列化(可能生成样板(或预处理 XML — 沿着以下行的简单 XSLT 就可以了:
<xsl:template match="foo">
<xsl:element name="{@id}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="bar">
<xsl:element name="{@name}">
<xsl:value-of select="@value"/>
</xsl:element>
</xsl:template>
更新:对于反向转换:
<xsl:template match="*[count(child::text())=1]">
<bar value="{text()}" name="{local-name()}"/>
</xsl:template>
<xsl:template match="*">
<foo id="{local-name()}">
<xsl:apply-templates/>
</foo>
</xsl:template>
我自己没有使用过 xml 序列化程序或反序列化程序,但我确实使用 LINQ 将我的 XML 文档解析为对象。如果你的课程相当简单,你可以研究这条路线。
由于您在评论中说,为了简单起见,您正在为 XmlSerializer 而努力,而不是因为该方法是由其他问题强制执行的,因此这里有一种不同的方法。由于元素的名称在文档中似乎无关紧要,因此我在解析中忽略了它,尽管也可以对其进行测试。对于更令人愉快的XML格式,这将是解析将关闭的主要内容(通常在元素名称上带有switch
(:
private static Document ParseDocument(XmlReader xr)
{
Document doc = new Document();
while(xr.Read())
if(xr.NodeType == XmlNodeType.Element)
if(xr.GetAttribute("id") == "customer")
doc.Customer = ParseCustomer(xr.ReadSubtree());
else
switch(xr.GetAttribute("name"))
{
case "somemoredata1":
doc.SomeMoreData1 = int.Parse(xr.GetAttribute("value"));
break;
case "somemoredata2":
doc.SomeMoreData2 = xr.GetAttribute("value");
break;
}
//Put some validation of doc here if necessary.
return doc;
}
private static Customer ParseCustomer(XmlReader xr)
{
Customer cu = new Customer();
while(xr.Read())
if(xr.NodeType == XmlNodeType.Element)
if(xr.GetAttribute("id") == "address")
cu.Address = ParseAddress(xr.ReadSubtree());
else
switch(xr.GetAttribute("name"))
{
case "firstname":
cu.FirstName = xr.GetAttribute("value");
break;
case "lastname":
cu.LastName = xr.GetAttribute("value");
break;
}
//validate here if necessary.
return cu;
}
private static Address ParseAddress(XmlReader xr)
{
Address add = new Address();
while(xr.Read())
if(xr.NodeType == XmlNodeType.Element)
switch(xr.GetAttribute("name"))
{
case "city":
add.City = xr.GetAttribute("value");
break;
case "country":
add.Country = xr.GetAttribute("value");
break;
}
return add;
}
它并不完全漂亮(它不是很漂亮,有漂亮的XML可以工作,但它往往没有那么糟糕(,但它可以工作,并且子树的使用对于一些复杂的结构来说可能很好,其中相同的类型可以出现在文档中的不同位置。可以将从外部设置值的静态方法替换为结构体,这些结构体采用XmlReader
,这允许人们确保类不变量和/或使对象不可变。
类型项目的大型系列(或仅包含几种类型的大型系列(的大型文档,此方法会发挥作用,因为可以在创建它们时将它们yield
出来,这可能会对第一次响应的延迟产生相当大的影响。
您可以尝试"XML 架构定义工具"(http://msdn.microsoft.com/de-de/library/x6c1kb0s%28v=vs.80%29.aspx (
再见! 斯特凡