2011-12-11 75 views
4

我需要爲元素實現可序列化的類型,其中包含具有類似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做任何假設。 這裏是原型實現這種類型的,如果我們有XmlReaderGetNamespacesInScope

[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?或者也許有另一種解決方案?

+0

你在創建它的地方「接收」xmlreader--給你選擇將它包裝在一個傳遞閱讀器中,該閱讀器跟蹤名稱空間並將包裝器傳遞給將使用它的東西? –

+1

在我的理解中,一個WCF編碼元素負責創建xmlreader,它可以是不同的,當前服務使用兩個編碼TextMessageEncoding和MtomMessageEncoding,第一個使用XmlUTF8TextReader,第二個使用XmlMtomReader(使用.net 4.0),但是沒有保證行爲將來不會改變,例如在.net 4.5中。在我看來,爲了控制創建xmlreader,我們需要重寫整個編碼綁定元素,在我看來,這是一項非常複雜的任務。 –

回答

3

我用這樣的代碼:

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

希望它能幫助, 拉杜

1

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

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