如何从 XmlReader 获取范围内的命名空间

and*_*.ko 5 .net c# xml wcf

我需要为包含具有类似 XPath 表达式的任何元素的序列的元素实现可序列化类型。它有非常简单的方案:

<xsd:complexType name="FilterType">
    <xsd:sequence>
        <xsd:any minOccurs="0" maxOccurs="unbounded" />
    </xsd:sequence>
</xsd:complexType>
Run Code Online (Sandbox Code Playgroud)

该元素的语义在WSBaseNotification主题 4.2 中进行了描述。问题是要解释表达式,我们需要某种机制来解析其中使用的前缀(XmlReader 通过 LookupNamespace 提供此类功能)。但还有一个问题,现阶段无法解析表达式,我们甚至无法对表达式类型和方言做出任何假设。所以我们需要以某种方式收集该范围内所有定义的前缀。一些XmlReader-s(例如XmlTextReader)实现了IXmlNamespaceResolver通过 GetNamespacesInScope 提供此类功能的接口,但其中许多没有(例如XmlMtomReader)。这个类型在很多web服务请求中使用,web服务使用wcf框架并且有几个绑定,所以我们不能对XmlReader将使用什么做任何假设。这是这种类型的原型实现,如果我们有GetNamespacesInScope对于XmlReader

[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;
}
}
Run Code Online (Sandbox Code Playgroud)

有什么方法可以实现GetNamespacesInScope所有可能的XmlReader吗?或者也许有另一种解决方案?

rad*_*scu 3

我使用这样的代码:

        XPathDocument doc = new XPathDocument("catalog.xml");
        XPathNavigator nav = doc.CreateNavigator();
        var v = nav.GetNamespacesInScope(XmlNamespaceScope.All);
Run Code Online (Sandbox Code Playgroud)

希望有帮助,拉杜