我需要支持两个非常相似但不同的xml文件的XML反序列化。
文件1:
<?xml version="1.0" encoding="UTF-8"?>
<lr:LogReport xmlns:dcml="http://www.x1.org/schemas/Types/"
xmlns:ds="http://www.x3.org/2000/09/xmldsig#"
xmlns:lr="http://www.x.org/schemas/LogRecord/"
xmlns:xs="http://www.x3.org/2001/XMLSchema"
xmlns:xsi="http://www.x3.org/2001/XMLSchema-instance">
<lr:reportDate>2010-03-05T07:00:52-08:00</lr:reportDate>
文件2:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<LogReport xmlns="http://www.x.org/schemas/LogRecord"
xmlns:dcml="http://www.x1.org/schemas/Types"
xmlns:ds="http://www.x3.org/2000/09/xmldsig#"
xmlns:lr="http://www.x.org/schemas/LogRecord"
xmlns:xs="http://www.x3.org/2001/XMLSchema"
xmlns:xsi="http://www.x3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.x.org/schemas/LogRecord ./LogRecord.xsd http://www.x1.org/schemas/Types ./Types.xsd">
<lr:reportDate>2010-02-26T07:00:02-08:00</lr:reportDate>
班级定义:
<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.smpte-ra.org/schemas/430-4/2008/LogRecord"), _
System.Xml.Serialization.XmlRootAttribute("LogReport", [Namespace]:="http://www.smpte-ra.org/schemas/430-4/2008/LogRecord", IsNullable:=False)> _
Partial Public Class LogReport
匹配File1的文件在匹配File2的文件成功时失败。关键区别在于两个命名空间定义的尾部斜杠。
代码示例:
Dim oLogReport As New LogReport
Dim oType As System.Type = oLogReport.GetType
Dim oReader As System.Xml.XmlReader = Nothing
Dim oSerializer As New XmlSerializer(oType)
oReader = System.Xml.XmlReader.Create(sFileName)
oLogReport = CType(oSerializer.Deserialize(oReader), LogReport)
File1出错:
{"<LogReport xmlns='http://www.x.org/schemas/LogRecord/'> was not expected."}
这些文件来自第三方,因此无法更改序列化过程。有没有办法支持这两种xml格式?我需要两个单独的课程吗?
谢谢!
答案 0 :(得分:2)
两个独立的班级模型是一个选项,虽然不是一个很好的选择。
您是否真的将这些文件作为XML然后在代码中处理,或者您是否正在使用应该自动反序列化XML的smoe类代理?
如果您正在进行自己的反序列化,我会考虑在执行反序列化之前创建一个简单的XSL转换来转换内存中的命名空间。用另一对简单地替换一对名称空间的转换将非常简短。
答案 1 :(得分:1)
到处尝试另外一个修复,因为我不喜欢做一个发现&amp;在xml文件中替换。
所以这是 - 我的机器上的工作 -
我首先使用 xsd.exe 生成了logRecordType
和logRecordHeaderType
类。请注意,我只需要解析logRecordHeader
元素,因此这里有一些额外的工作。但修复基本上是使用FixupNameTable
,以便每次出现带有尾部斜杠的命名空间都替换为没有它的那个。
namespace DolbyService.Schemas
{
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
public partial class logRecordType
{
public const string xmlns_lr = "http://www.smpte-ra.org/schemas/430-4/2008/LogRecord";
public const string xmlns_dcml = "http://www.smpte-ra.org/schemas/433/2008/dcmlTypes";
public static IEnumerable<logRecordHeaderType> Parse(Stream xmlfile)
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.NameTable = new FixupNameTable();
using (var rdr = XmlReader.Create(xmlfile, settings))
{
var headerSerialize = new XmlSerializer(typeof(logRecordHeaderType));
while (rdr.ReadToFollowing(logRecordHeaderType.LogRecordHeader, logRecordType.xmlns_lr))
{
using (var subreader = rdr.ReadSubtree())
{
var ok = headerSerialize.CanDeserialize(subreader);
var logRecordHeader = headerSerialize.Deserialize(subreader);
yield return logRecordHeader as logRecordHeaderType;
}
}
}
}
}
internal class FixupNameTable : XmlNameTable
{
private NameTable _table = new NameTable();
public override string Add(string key)
{
key = ReplaceKey(key);
return _table.Add(key);
}
private static string ReplaceKey(string key)
{
if (key.StartsWith(logRecordType.xmlns_lr)) key = logRecordType.xmlns_lr;
if (key.StartsWith(logRecordType.xmlns_dcml)) key = logRecordType.xmlns_dcml;
return key;
}
public override string Add(char[] array, int offset, int length)
{
return _table.Add(array, offset, length);
}
public override string Get(string key)
{
key = ReplaceKey(key);
return _table.Get(key);
}
public override string Get(char[] array, int offset, int length)
{
return _table.Get(array, offset, length);
}
}
[XmlRoot(logRecordHeaderType.LogRecordHeader, Namespace = logRecordType.xmlns_lr, IsNullable = false)]
public partial class logRecordHeaderType
{
public const string LogRecordHeader = "LogRecordHeader";
private static XmlSerializer _ser = new XmlSerializer(typeof(logRecordHeaderType));
public static logRecordHeaderType Deserialize(XmlReader xmlReader)
{
return _ser.Deserialize(xmlReader) as logRecordHeaderType;
}
public static bool CanDeserialize(XmlReader xmlReader)
{
return _ser.CanDeserialize(xmlReader);
}
}
public class HeaderComparer : IEqualityComparer<logRecordHeaderType>
{
public bool Equals(logRecordHeaderType x, logRecordHeaderType y)
{
return x.EventID == y.EventID;
}
public int GetHashCode(logRecordHeaderType obj)
{
return obj.EventID.GetHashCode();
}
}
}
答案 2 :(得分:0)
如果名称空间不同,那么XML就不同了。