重复:
Omitting all xml namespaces when serializing an object? 不一样..我想用另一种方式:反序列化!
我有一个C#类如下:
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.portalfiscal.inf.br/nfe")]
[System.Xml.Serialization.XmlRootAttribute("NFe", Namespace = "http://www.portalfiscal.inf.br/nfe", IsNullable = false)]
public partial class TNFe
{
private TNFeInfNFe infNFeField;
private SignatureType signatureField;
/// <remarks/>
public TNFeInfNFe infNFe
{ ...
我使用此类按用户请求序列化/反序列化XML文件。 但是我遇到了一个问题:在这个软件的新版本中添加了名称空间定义。 XML仍然是相同的,只添加名称空间定义。
例如,最后一个版本......
<?xml version="1.0" encoding="utf-8" ?>
<NFe>
<infNFe version="1.10">
...
和新版本......
<?xml version="1.0" encoding="utf-8" ?>
<NFe xmlns="http://www.portalfiscal.inf.br/nfe">
<infNFe version="2.10">
...
我需要加载带有和不带这些名称空间的XML文件。 我有很多嵌套类,每个嵌套类都有自己的命名空间定义。
我想对两个XML使用相同的类,有和没有名称空间。
我尝试创建一个XmlTextReader并覆盖NamespaceURI方法,但我仍然收到一个没有太多信息的异常。我认为.NET引擎正在尝试针对XML强制类命名空间定义。
答案 0 :(得分:8)
为了在没有命名空间的情况下反序列化XML,请将XmlRoot属性添加到代表层次结构顶部的类中:
[XmlRoot(ElementName="plugins", Namespace="")]
在我的示例中,Xml没有名称空间,并且像
一样启动<plugins><...
它反序列化的类:
[XmlRoot(ElementName="plugins", Namespace="")]
public class Plugins
{
//...
}
显然,您的情况可能略有不同,但此代码适用于我:
using (FileStream stream = File.Open(filePath, FileMode.Open))
{
XmlReader reader = new XmlTextReader(stream);
XmlSerializer serializer = new XmlSerializer(typeof(Plugins));
var plugins = (Plugins)serializer.Deserialize(reader);
}
-Stan
答案 1 :(得分:7)
我遇到了类似的代理类挑战。由于我不打算进入的原因,我需要使用Web服务器上的XmlSerializer手动序列化类,并在客户端上反序列化。我无法在线找到优雅的解决方案,所以我通过在Visual Studio中自动生成XmlTypeAttribute后手动删除XmlTypeAttribute来避免这个问题。
我一直回过头来看看是否有办法让命名空间进行锻炼。以下是我在不需要修改自动生成的类的情况下工作的方法。我最终使用XmlTextReader在匹配属性名称的节点上返回所需的命名空间。还有改进的余地,但我希望它有所帮助。
class Program
{
static void Main(string[] args)
{
//create list to serialize
Person personA = new Person() { Name = "Bob", Age = 10, StartDate = DateTime.Parse("1/1/1960"), Money = 123456m };
List<Person> listA = new List<Person>();
for (int i = 0; i < 10; i++)
{
listA.Add(personA);
}
//serialize list to file
XmlSerializer serializer = new XmlSerializer(typeof(List<Person>));
XmlTextWriter writer = new XmlTextWriter("Test.xml", Encoding.UTF8);
serializer.Serialize(writer, listA);
writer.Close();
//deserialize list from file
serializer = new XmlSerializer(typeof(List<ProxysNamespace.Person>));
List<ProxysNamespace.Person> listB;
using (FileStream file = new FileStream("Test.xml", FileMode.Open))
{
//configure proxy reader
XmlSoapProxyReader reader = new XmlSoapProxyReader(file);
reader.ProxyNamespace = "http://myappns.com/"; //the namespace of the XmlTypeAttribute
reader.ProxyType = typeof(ProxysNamespace.Person); //the type with the XmlTypeAttribute
//deserialize
listB = (List<ProxysNamespace.Person>)serializer.Deserialize(reader);
}
//display list
foreach (ProxysNamespace.Person p in listB)
{
Console.WriteLine(p.ToString());
}
Console.ReadLine();
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public DateTime StartDate { get; set; }
public decimal Money { get; set; }
}
namespace ProxysNamespace
{
[XmlTypeAttribute(Namespace = "http://myappns.com/")]
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public DateTime Birthday { get; set; }
public decimal Money { get; set; }
public override string ToString()
{
return string.Format("{0}:{1},{2:d}:{3:c2}", Name, Age, Birthday, Money);
}
}
}
public class XmlSoapProxyReader : XmlTextReader
{
List<object> propNames;
public XmlSoapProxyReader(Stream input)
: base(input)
{
propNames = new List<object>();
}
public string ProxyNamespace { get; set; }
private Type proxyType;
public Type ProxyType
{
get { return proxyType; }
set
{
proxyType = value;
PropertyInfo[] properties = proxyType.GetProperties();
foreach (PropertyInfo p in properties)
{
propNames.Add(p.Name);
}
}
}
public override string NamespaceURI
{
get
{
object localname = LocalName;
if (propNames.Contains(localname))
return ProxyNamespace;
else
return string.Empty;
}
}
}
答案 2 :(得分:1)
您可以将文件作为文本读取,删除有问题的命名空间文本,然后对其进行反序列化。
您可能需要将“好”文本写回[memory / string / etc]流,以便可以调用XmlSerializer的Deserialize。
答案 3 :(得分:-1)
您需要实现IXmlSerializable以改进自定义序列化。