如何从XmlReader获得范围内的命名空间
问题描述:
我需要为元素实现可序列化的类型,其中包含具有类似XPath表达式的任何元素的序列。 这是一个非常简单的方案:如何从XmlReader获得范围内的命名空间
<xsd:complexType name="FilterType">
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
语义元素浓缩于WSBaseNotification话题4.2描述。 问题是,为了解释表达式,我们需要一些机制来解析在其中使用的前缀(XmlReader通过LookupNamespace提供这样的功能)。但还有另一个问题,现阶段不可能解析表达,我们现在甚至不能对表情类型和方言做出任何假设。所以我们需要以某种方式收集该范围内的所有已定义的前缀。某些XmlReader
-s(例如XmlTextReader
)实现了接口IXmlNamespaceResolver
,它们通过GetNamespacesInScope提供了此类功能,但其中很多都没有(例如XmlMtomReader
)。这种类型在许多Web服务请求中使用,Web服务使用wcf框架并有几个绑定,所以我们不能对使用什么XmlReader
做任何假设。 这里是原型实现这种类型的,如果我们有XmlReader
GetNamespacesInScope
:
[Serializable]
public class FilterType : IXmlSerializable {
public XElement[] Any;
public void ReadXml(XmlReader reader) {
var xelist = new LinkedList<XElement>();
reader.Read();
var dr = reader as XmlDictionaryReader;
var gns = reader.GetNamespacesInScope(); // need to implement
while (reader.NodeType != XmlNodeType.EndElement) {
if (reader.NodeType == XmlNodeType.Element) {
var x = XElement.ReadFrom(reader) as XElement;
foreach (var ns in gns) {
var pref = ns.Key;
var uri = ns.Value;
if (x.GetNamespaceOfPrefix(pref) == null) {
x.Add(new XAttribute(XName.Get(pref, "http://www.w3.org/2000/xmlns/"), uri));
}
}
xelist.AddLast((XElement)x);
} else {
reader.Skip();
}
}
Any = xelist.ToArray();
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer) {
if (Any != null) {
foreach (var x in Any) {
x.WriteTo(writer);
}
}
}
public XmlSchema GetSchema() {
return null;
}
}
有什么办法来实现GetNamespacesInScope
每一个可能的XmlReader
?或者也许有另一种解决方案?
答
我用这样的代码:
XPathDocument doc = new XPathDocument("catalog.xml");
XPathNavigator nav = doc.CreateNavigator();
var v = nav.GetNamespacesInScope(XmlNamespaceScope.All);
希望它能帮助, 拉杜
答
您可能,但是,需要一个命名空间管理器 - 例如:
XmlElement el = ...; //TODO
XmlNamespaceManager nsmgr = new XmlNamespaceManager(
el.OwnerDocument.NameTable);
nsmgr.AddNamespace("x", el.OwnerDocument.DocumentElement.NamespaceURI);
var nodes = el.SelectNodes(@"/x:outerelement/x:innerelement", nsmgr);
你在创建它的地方“接收”xmlreader--给你选择将它包装在一个传递阅读器中,该阅读器跟踪名称空间并将包装器传递给将使用它的东西? –
在我的理解中,一个WCF编码元素负责创建xmlreader,它可以是不同的,当前服务使用两个编码TextMessageEncoding和MtomMessageEncoding,第一个使用XmlUTF8TextReader,第二个使用XmlMtomReader(使用.net 4.0),但是没有保证行为将来不会改变,例如在.net 4.5中。在我看来,为了控制创建xmlreader,我们需要重写整个编码绑定元素,在我看来,这是一项非常复杂的任务。 –