【问题标题】:how to get namespaces in scope from XmlReader如何从 XmlReader 获取范围内的命名空间
【发布时间】:2011-12-11 19:04:05
【问题描述】:

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

<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会使用什么做任何假设。 这是这种类型的原型实现,如果我们有GetNamespacesInScope for 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;
}
}

有没有办法为每个可能的XmlReader 实现GetNamespacesInScope?或者也许还有其他解决方案?

【问题讨论】:

  • 您是否在创建 xmlreader 时“接收”它 - 让您可以选择将其包装在一个传递阅读器中,该阅读器跟踪命名空间并将包装器传递给将使用它的对象?
  • 据我了解,一个 WCF 编码元素负责创建 xmlreader,可以不同,目前服务使用两种编码 TextMessageEncoding 和 MtomMessageEncoding,第一个使用 XmlUTF8TextReader,第二个使用 XmlMtomReader(在 .net 4.0 中)但不能保证这种行为将来不会改变,例如在 .net 4.5 中。在我看来,要控制创建 xmlreader,我们需要重写整个编码绑定元素,在我看来这是一项非常复杂的任务。

标签: c# .net xml wcf


【解决方案1】:

我使用这样的代码:

        XPathDocument doc = new XPathDocument("catalog.xml");
        XPathNavigator nav = doc.CreateNavigator();
        var v = nav.GetNamespacesInScope(XmlNamespaceScope.All);

希望对你有帮助, 拉度

【讨论】:

    【解决方案2】:

    但是,您可能需要一个命名空间管理器 - 例如:

    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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-26
      • 1970-01-01
      • 1970-01-01
      • 2011-08-25
      • 1970-01-01
      • 1970-01-01
      • 2011-08-28
      • 2011-06-21
      相关资源
      最近更新 更多