我正在努力学习反序列化。我编写了这段代码来反序列化* .hbm.xml文件。
每个元素都正确加载,但是“xmlns”。异常中的消息是:
<hibernate-mapping xmlns='urn:nhibernate-mapping-2.2'> was not expected.
应该怎样解决这个问题?
您想查看我的完整代码吗?
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping
assembly="Sample.CustomerService.Domain" namespace="Sample.CustomerService.Domain"
>
<class name="MyTable" table="MyTable" lazy="true" >
<id name="ID">
<generator class="identity" />
<column name="ID" sql-type="int" not-null="true" />
</id>
<property name="Name">
<column name="Name" sql-type="varchar" not-null="false" />
</property>
<property name="MfgDate">
<column name="MfgDate" sql-type="datetime" not-null="true" />
</property>
</class>
</hibernate-mapping>
public class Class
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("table")]
public string Table { get; set; }
[XmlAttribute("lazy")]
public bool Lazy { get; set; }
[XmlElement("id")]
public Id Id { get; set; }
[XmlElement("property")]
public Property [] Properties { get; set; }
}
public class Column
{
[XmlAttribute("name")]
public string ColumnName { get; set; }
[XmlAttribute("sql-type")]
public string SqlTypeName { get; set; }
[XmlAttribute("not-null")]
public bool NotNull { get; set; }
}
public class Generator
{
[XmlAttribute("class")]
public string Class { get; set; }
}
[XmlRoot("hibernate-mapping", Namespace = "urn:nhibernate-mapping-2.2")]
public class HibernateMapping
{
[XmlAttribute("assembly")]
public string AssemblyName { get; set; }
[XmlAttribute("namespace")]
public string NamespaceName { get; set; }
[XmlElement("class")]
public Class Class { get; set; }
public override string ToString()
{
StringBuilder sb = new StringBuilder(NamespaceName);
sb.Append(".");
sb.Append(Class.Name);
return sb.ToString();
}
}
public class Id
{
[XmlElement("generator")]
public Generator Generator { get; set; }
[XmlElement("column")]
public Column Column { get; set; }
}
public class Property
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("column")]
public string Column { get; set; }
[XmlAttribute("type")]
public string SqlTypeName { get; set; }
[XmlAttribute("not-null")]
public bool NotNull { get; set; }
[XmlElement("column")]
public Column PropColumn { get; set; }
public string GetColumnName()
{
if (PropColumn != null)
{
return PropColumn.ColumnName;
}
else
{
return Name;
}
}
public string GetSqlTypeName()
{
if (PropColumn != null)
{
return PropColumn.SqlTypeName;
}
else
{
return SqlTypeName;
}
}
public bool GetNotNull()
{
if (PropColumn != null)
{
return PropColumn.NotNull;
}
else
{
return NotNull;
}
}
}
class Program
{
static void Main(string[] args)
{
//IList<HibernateMapping> list = HbmReader.Get("How_To_Deserialize_a_Hbm_File");
// string xml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
//<hibernate-mapping xmlns=""urn:nhibernate-mapping-2.2"">
// <class name=""Example.Library.Resources.TestObject, Example.Library"" table=""test_object"" lazy=""false"">
// <id name=""TestId"" column=""TestId"" type=""Guid"">
// <generator class=""assigned"" />
// </id>
// <property name=""Name"" type=""String"" length=""45"" />
// </class>
//</hibernate-mapping>";
Assembly assembly = Assembly.Load("Sample.CustomerService.Domain");
string[] manifestResourceNames = assembly.GetManifestResourceNames();
XmlSerializer ser = new XmlSerializer(typeof(HibernateMapping));
Stream stream = assembly.GetManifestResourceStream(manifestResourceNames[0]);
HibernateMapping obj = (HibernateMapping)ser.Deserialize(new StreamReader(stream));
Console.WriteLine(obj.Class.Name);
Console.WriteLine(obj.Class.Table);
foreach (var prop in obj.Class.Properties)
{
Console.WriteLine("prop: " + prop.Name);
}
string str = string.Empty;
}
}
答案 0 :(得分:3)
xmlns
(xml名称空间)属性保留给XML。 XmlSerializer永远不会将它返回给你。
答案 1 :(得分:3)
只需使用Namespace
,XmlRoot
,XmlType
和XmlAttribute
(等)上的XmlElement
属性即可解决此问题。示例如下所示:
输出:
Example.Library.Resources.TestObject, Example.Library
test_object
prop: Name
Xml(from here):
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Example.Library.Resources.TestObject, Example.Library" table="test_object" lazy="false">
<id name="TestId" column="TestId" type="Guid">
<generator class="assigned" />
</id>
<property name="Name" type="String" length="45" />
</class>
</hibernate-mapping>
C#:
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
[XmlRoot("hibernate-mapping", Namespace = "urn:nhibernate-mapping-2.2")]
public class HibernateMapping
{
[XmlAttribute("assembly")]
public string AssemblyName { get; set; }
[XmlElement("class")] // should this be a list?
public Class Class { get; set; }
}
public class Class
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("table")]
public string Table { get; set; }
private readonly List<Property> properties = new List<Property>();
[XmlElement("property")]
public List<Property> Properties { get { return properties; } }
}
public class Property
{
[XmlAttribute("name")]
public string Name { get; set; }
}
static class Program
{
static void Main()
{
File.WriteAllText("my.xml",
@"<?xml version=""1.0"" encoding=""utf-8"" ?>
<hibernate-mapping xmlns=""urn:nhibernate-mapping-2.2"">
<class name=""Example.Library.Resources.TestObject, Example.Library"" table=""test_object"" lazy=""false"">
<id name=""TestId"" column=""TestId"" type=""Guid"">
<generator class=""assigned"" />
</id>
<property name=""Name"" type=""String"" length=""45"" />
</class>
</hibernate-mapping>");
var ser = new XmlSerializer(typeof(HibernateMapping));
var obj = (HibernateMapping)ser.Deserialize(new StreamReader("my.xml"));
Console.WriteLine(obj.Class.Name);
Console.WriteLine(obj.Class.Table);
foreach (var prop in obj.Class.Properties)
{
Console.WriteLine("prop: " + prop.Name);
}
Console.ReadKey();
}
}
注意我只映射了一些xml值 - 但它应该表明它基本上有效。
答案 2 :(得分:1)
自.NET类型以来,序列化程序不知道XML命名空间 没有宣布它。
您需要添加以下属性以确保序列化程序 考虑命名空间:
[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:nhibernate-mapping-2.2")]
[System.Xml.Serialization.XmlRootAttribute("SupportedAgreementType", Namespace="urn:nhibernate-mapping-2.2", Nullable=false)]
答案 3 :(得分:0)
您可以使用IXmlSerializable,而不是尝试自动实现反序列化。当你习惯它并且非常灵活时,它真的很容易。您可以使用私有支持而不是公共访问器来实例化只读属性。它比属性映射更冗长,但是这里有一些你可以使用的代码(我在这里做了不同的事情,让你知道事情是如何工作的):
[Serializable(), XmlRoot("hibernate-mapping", Namespace = "urn:nhibernate-mapping-2.2")]
public class HibernateMapping : IXmlSerializable
{
public string AssemblyName { get; set; }
public string NamespaceName { get; set; }
public Class Class { get; set; }
public override string ToString()
{
StringBuilder sb = new StringBuilder(NamespaceName);
sb.Append(".");
sb.Append(Class.Name);
return sb.ToString();
}
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
AssemblyName = reader["assembly"];
NamespaceName = reader["namespace"];
XmlSerializer classSerializer = new XmlSerializer(typeof(Class));
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.LocalName)
{
case "class":
Class = (Class)classSerializer.Deserialize(reader.ReadSubtree());
break;
}
}
}
}
public void WriteXml(XmlWriter writer)
{
throw new NotImplementedException();
}
}
public class Column
{
public string ColumnName { get; set; }
public string SqlTypeName { get; set; }
public bool NotNull { get; set; }
}
public class Generator
{
public string Class { get; set; }
}
public class Id
{
public Generator Generator { get; set; }
public Column Column { get; set; }
}
public class Property
{
public string Name { get; set; }
public string Column { get; set; }
public string SqlTypeName { get; set; }
public bool NotNull { get; set; }
public Column PropColumn { get; set; }
public string GetColumnName()
{
if (PropColumn != null) { return PropColumn.ColumnName; }
else { return Name; }
}
public string GetSqlTypeName()
{
if (PropColumn != null) { return PropColumn.SqlTypeName; }
else { return SqlTypeName; }
}
public bool GetNotNull()
{
if (PropColumn != null) { return PropColumn.NotNull; }
else { return NotNull; }
}
}
[Serializable(), XmlRoot("class")]
public class Class : IXmlSerializable
{
public string Name { get; set; }
public string Table { get; set; }
public bool Lazy { get; set; }
public Id Id { get; set; }
public Property[] Properties { get; set; }
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
Name = reader["name"];
Table = reader["table"];
Lazy = Convert.ToBoolean(reader["lazy"]);
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.LocalName)
{
case "id":
ReadIdXml(reader.ReadSubtree());
break;
case "property":
ReadPropertyXml(reader.ReadSubtree());
break;
}
}
}
}
private void ReadIdXml(XmlReader reader)
{
//you can read the attributes and subnodes of the id node as above...
Id = new Id();
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.LocalName)
{
case "generator":
Id.Generator = new Generator();
Id.Generator.Class = reader["class"];
break;
case "column":
Id.Column = ReadColumnXml(reader.ReadSubtree());
break;
}
}
}
}
private void ReadPropertyXml(XmlReader reader)
{
Property property = new Property();
property.Name = reader["name"];
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.LocalName)
{
case "generator":
property.PropColumn = ReadColumnXml(reader.ReadSubtree());
break;
}
}
}
}
private Column ReadColumnXml(XmlReader reader)
{
Column column = new Column();
column.ColumnName = reader["name"];
column.SqlTypeName = reader["sql-type"];
column.NotNull = Convert.ToBoolean(reader["non-null"]);
return column;
}
public void WriteXml(System.Xml.XmlWriter writer)
{
throw new NotImplementedException();
}
}