我想使用忽略命名空间的XmlTextReader
而不检查字符。要忽略名称空间,我可以设置属性Namespaces=false
,而不检查我可以使用XmlReaderSettings.CheckCharacters = false
的字符。
我尝试使用它构造函数创建XmlTextReader
,但这不允许我传入已配置的XmlReaderSettings
。属性Settings
是只读的,因此我无法在构造后设置它。
XmlTextReader reader = new XmlTextReader(gzs) { Namespaces = false};
reader.Settings = new XmlReaderSettings { CheckCharacters = false}; // readonly
使用基类Create()
的静态方法XmlReader
我可以传入XmlReaderSettings
,但该方法返回XmlTextReaderImpl
并且没有属性{{1设置并且无法转换为Namespace
。
XmlTextReader
那么如何创建这样的XmlTextReader呢?它甚至可能吗? var settings = new XmlReaderSettings { CheckCharacters = false};
var reader = XmlTextReader.Create(gzs, settings);
XmlTextReader textReader = reader as XmlTextReader // not possible
上是否有任何属性可以忽略命名空间?
答案 0 :(得分:2)
这并不难。
我的任务是反序列化相同结构的xml文件,这些文件可以带有或不带有默认的名称空间声明。
首先,我使用XmlTextReader解决方案找到了这个discussion:NamespaceIgnorantXmlTextReader。 但MSDN建议不要使用XmlTextReader并改为使用XmlReader。
所以我们需要在XmlReader上做同样的事情。
XmlReader是一个抽象类,我们需要先做一个包装器。 Here是一篇很好的文章,如何做到这一点。 here是一个现成的XmlWrappingReader。
然后我们需要扩展它:
public class XmlExtendableReader : XmlWrappingReader
{
private bool _ignoreNamespace { get; set; }
public XmlExtendableReader(TextReader input, XmlReaderSettings settings, bool ignoreNamespace = false)
: base(XmlReader.Create(input, settings))
{
_ignoreNamespace = ignoreNamespace;
}
public override string NamespaceURI
{
get
{
return _ignoreNamespace ? String.Empty : base.NamespaceURI;
}
}
}
那就是它。现在我们可以使用它来控制XmlReaderSettings和命名空间处理:
XmlReaderSettings settings = new XmlReaderSettings()
{
CheckCharacters = false,
ConformanceLevel = ConformanceLevel.Document,
DtdProcessing = DtdProcessing.Ignore,
IgnoreComments = true,
IgnoreProcessingInstructions = true,
IgnoreWhitespace = true,
ValidationType = ValidationType.None
};
using (XmlExtendableReader xmlreader = new XmlExtendableReader(reader, settings, true))
_entities = ((Orders)_serializer.Deserialize(xmlreader)).Order;
答案 1 :(得分:0)
在我的情况下,作为提供程序的api版本控制策略的一部分,我遇到了在使用XmlSerializer反序列化到同一C#类时支持不同的响应名称空间的需求。
响应基本上是相同的,但是响应中的根名称空间根据传递给服务的凭据而有所不同。
因此,我使用XmlWrappingReader方法将服务返回的名称空间重命名为C#类通过XmlTypeAttribute附加的名称空间。
但有一个警告:使用字符串插入,因为我怀疑XmlSerializer在从XmlReader读取以匹配c#类中的目标名称空间时正在使用Object.ReferenceEquals。
在我的情况下,replaceNs参数是通过反射从类型的XmlTypeAttribute获得的,显然与XmlSerializer内部使用的字符串不是完全相同的对象引用。
我几乎因为这种愚蠢的事情而掉了头发……
public class ReplaceNsXmlReader : XmlWrappingReader
{
private readonly string replacementNs;
public ReplaceNsXmlReader(XmlReader reader, string replacementNs)
: base(reader)
{
//
// NOTE: String.Intern is here needed for the XmlSerializer
// that will be using this reader to deserialize correctly
//
this.replacementNs = String.Intern(replacementNs);
}
public override string NamespaceURI
{
get => replacementNs;
}
}