I need to implement serializable type for element which contains a sequence of any elements with XPath-like expressions. It has very simple scheme:
<xsd:complexType name="FilterType">
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
The semantic of this element is described in WSBaseNotification topic 4.2.
The problem is that to interpret an expression we need some mechanism to resolve prefixes that was used in it (XmlReader provide such functionality via LookupNamespace). But there is another problem that it is not possible to parse expression at this stage, we even can not make any assumptions about expression type and dialect at this moment. So we need somehow collect all defined prefixes in that scope. Some of XmlReader
-s (for example XmlTextReader
) implements interface IXmlNamespaceResolver
which provide such functionality via GetNamespacesInScope but many of them didn't (for example XmlMtomReader
). This type used in many web service requests, the web service use wcf framework and have several bindings, so we can not make any assumption about what XmlReader
will be used.
Here is prototype implementation of such type, if we have 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 any way to implement GetNamespacesInScope
for every possible XmlReader
? Or maybe there is another solution?
Specifying a target namespace. The following XSD schema specifies a target namespace by using the xsd:targetNamespace attribute. The schema also sets the elementFormDefault and attributeFormDefault attribute values to "unqualified" (the default value for these attributes).
XML Namespaces - The xmlns Attribute When using prefixes in XML, a namespace for the prefix must be defined. The namespace can be defined by an xmlns attribute in the start tag of an element. The namespace declaration has the following syntax. xmlns:prefix="URI".
Figure 1: Elements and attributes in XML Schema namespace are used to write an XML Schema document, which generates elements and attributes as defined by user and puts them in {target namespace}. This {target namespace} is then used to validate the XML instance.
Most business and communications problems that XML can solve require a combination of several XML vocabularies. XML has a mechanism for qualifying names to be allocated into different namespaces, such as namespaces that apply to different industries.
I use the code like this :
XPathDocument doc = new XPathDocument("catalog.xml");
XPathNavigator nav = doc.CreateNavigator();
var v = nav.GetNamespacesInScope(XmlNamespaceScope.All);
Hope it helps, Radu
You may, however, 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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With