英文:
adding Xml attributes to objects serialized from .NET
问题
以下是您要翻译的内容:
I have a class called CustomerDetails, and I manage these objects in a System.Collections.Generic.List(Of CustomerDetails). I serialize this object in an ordinary way...
Private Sub CustomerDetailsExportToXml(Details As System.Collections.Generic.List(Of CustomerDetails))
Dim x As New System.Xml.Serialization.XmlSerializer(Details.GetType)
Using s As New FileStream("customerdetails.xml", FileMode.Create)
x.Serialize(s, Details)
End Using
End Sub
...and get ordinary Xml...
MSD
To aid readability, I want to add an attribute to the CustomerDetails tag called "Acronym" that would contain the value of the tag:
I can do this in a post-serialization method where I load/modify/save the Xml, but I'm afraid of the resulting Xml not being de-serializable. Can the addition of the attribute be done at time of serialization?
英文:
I have a class called CustomerDetails, and I manage these objects in a System.Collections.Generic.List(Of CustomerDetails). I serialize this object in an ordinary way...
Private Sub CustomerDetailsExportToXml(Details As System.Collections.Generic.List(Of CustomerDetails))
Dim x As New System.Xml.Serialization.XmlSerializer(Details.GetType)
Using s As New FileStream("customerdetails.xml", FileMode.Create)
x.Serialize(s, Details)
End Using
End Sub
...and get ordinary Xml...
<?xml version="1.0"?>
<ArrayOfCustomerDetails xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CustomerDetails>
<Acronym>MSD</Acronym>
<FriendlyName>Main Street Diner</FriendlyName>
</CustomerDetails>
</ArrayOfCustomerDetails>
To aid readability, I want to add an attribute to the CustomerDetails tag called "Acronym" that would contain the value of the <Acronym> tag:
<CustomerDetails Acronym="MSD">
I can do this in a post-serialization method where I load/modify/save the Xml, but I'm afraid of the resulting Xml not being de-serializable. Can the addition of the attribute be done at time of serialization?
答案1
得分: 2
以下是翻译好的内容:
自从您似乎已经有与element相同值的Acronym
,这应该很容易让序列化程序为您完成。很可能现在您有类似这样的内容:
public class CustomerDetails
{
public string Acronym {get;set;}
}
要将其变成一个属性,您只需要这样做:
public class CustomerDetails
{
[XmlAttribute]
public string Acronym {get;set;}
}
您也可以在没有属性的情况下通过手动配置序列化程序来实现,但这需要更多的工作。
英文:
Since you already seem to have Acronym
with the same value as an element, this should be pretty simple to get the serializer to do for you. Presumably right now you have something like:
public class CustomerDetails
{
public string Acronym {get;set;}
}
To make that an attribute instead, all you have to do is ask:
public class CustomerDetails
{
[XmlAttribute]
public string Acronym {get;set;}
}
You can also do this without attributes by configuring the serializer manually, but it is a lot more work.
答案2
得分: 1
更新
Marc Gravell的回答更为简洁,并保持易于反序列化。
这里有一个使用XmlAttribute装饰器的示例:https://dotnetfiddle.net/6T0U4d
原始回答
> 我可以在后序列化的方法中做到这一点,在那里我加载/修改/保存Xml,但我担心生成的Xml可能无法反序列化。可以在序列化时添加属性吗?
是的,你是正确的。如果你干扰序列化输出,那么它可能无法被反序列化。
然而,你所询问的可以通过以下步骤轻松实现:
- 不使用
FileStream
,而是使用StringWriter
将输出作为内存字符串获取 - 将XML文本加载到
XDocument
中 - 循环遍历ArrayOfCustomerDetails元素中的CustomerDetails元素
- 将属性值设置为Acronym元素的值
- 移除Acronym元素
- 将XDocument XML保存到文件中
例如:
Dim serializer = New XmlSerializer(details.GetType())
Dim xmlLiteral = String.Empty
Using writer = New StringWriter()
serializer.Serialize(writer, details)
xmlLiteral = writer.ToString()
End Using
Dim detailsXmlDocument = XDocument.Parse(xmlLiteral)
For Each customerDetailsElement In detailsXmlDocument.Element("ArrayOfCustomerDetails").Elements("CustomerDetails")
customerDetailsElement.SetAttributeValue("Acronym", customerDetailsElement.Element("Acronym").Value)
customerDetailsElement.Element("Acronym").Remove()
Next
IO.File.WriteAllText("customerdetails.xml", detailsXmlDocument.ToString())
Fiddle: https://dotnetfiddle.net/kAz5Ol
你可以通过简单地反转这个过程使反序列化工作。
英文:
Update
Marc Gravell's answer is much more concise and keeps it so it can be deserialized easily too.
Here is a fiddle using the XmlAttribute decorator: https://dotnetfiddle.net/6T0U4d
Original Answer
> I can do this in a post-serialization method where I load/modify/save the Xml, but I'm afraid of the resulting Xml not being de-serializable. Can the addition of the attribute be done at time of serialization?
That is correct. If you mess with the serialization output then it is unlikely that it will be deserializable.
However, what you're asking can be done pretty easily by following these steps:
- Instead of using a
FileStream
you can use aStringWriter
to get the output as an in-memory string - Take the XML literal and load it into an
XDocument
- Loop over the CustomerDetails elements in the ArrayOfCustomerDetails element
- Set the attribute value to the Acronym element value
- Remove the Acronym element
- Save the XDocument XML to your file
For example:
Dim serializer = New XmlSerializer(details.GetType())
Dim xmlLiteral = String.Empty
Using writer = New StringWriter()
serializer.Serialize(writer, details)
xmlLiteral = writer.ToString()
End Using
Dim detailsXmlDocument = XDocument.Parse(xmlLiteral)
For Each customerDetailsElement In detailsXmlDocument.Element("ArrayOfCustomerDetails").Elements("CustomerDetails")
customerDetailsElement.SetAttributeValue("Acronym", customerDetailsElement.Element("Acronym").Value)
customerDetailsElement.Element("Acronym").Remove()
Next
IO.File.WriteAllText("customerdetails.xml", detailsXmlDocument.ToString())
Fiddle: https://dotnetfiddle.net/kAz5Ol
You could get the deserialization to work by just reversing the process.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论