How to get namespaces in scope from XmlReader

I need to implement a serializable type for an element that contains a sequence of any elements with XPath expressions. It has a very simple scheme:

<xsd:complexType name="FilterType"> <xsd:sequence> <xsd:any minOccurs="0" maxOccurs="unbounded" /> </xsd:sequence> </xsd:complexType> 

The semantics of this element are described in WSBaseNotification in section 4.2. The problem is that in order to interpret the expression, we need some mechanism to eliminate the prefixes that were used in it (XmlReader provides such functionality through LookupNamespace). But there is another problem that at this stage it is impossible to parse the expression, we can’t even make any assumptions about the type of expression and the dialect at the moment. Therefore, we need to somehow collect all the specific prefixes in this area. Some of the XmlReader -s (for example, XmlTextReader ) implement the IXmlNamespaceResolver interface, which provides this functionality through GetNamespacesInScope, but many of them did not (for example, XmlMtomReader ). This type is used in many requests for web services, the web service uses the wcf framework and has several bindings, so we can not make any assumptions that XmlReader will be used. Here is a prototype of this type of implementation if 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; } } 

Is there a way to implement GetNamespacesInScope for all possible XmlReader ? Or maybe there is another solution?

+4
source share
2 answers

I use the code as follows:

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

Hope this helps, Radu

+3
source

However, you may need a namespace manager, for example:

 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); 
+1
source

Source: https://habr.com/ru/post/1385776/


All Articles