Handle xml namespaces with xpath / reading and writing?

D

DC

Hi,

in the file listed below I have to programmatically changes some
element values.

I am currently reading the document into an xmldocument, and then
locating the element to modify with xpath, then I change the element
in memory and write the entire document back to disk. I did not find a
more elegant way.

But once a default namespace apeared like in the example below,
everything broke. I certainly have to regard namespaces, but I think
there is no automatic handling in .net? I guess since I read and write
the whole document, I must examine all xmlns attributes and declare
them? Or is there maybe an easy way out?

TIA for any hints,

Regards
DC

xml version="1.0" encoding="utf-8"?>
<dataConfiguration>
<xmlSerializerSection>
<enterpriseLibrary.databaseSettings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
defaultInstance="CmsContent"
xmlns="http://www.microsoft.com/practices/enterpriselibrary/
08-31-2004/data">
<databaseTypes>
<databaseType name="Sql Server" />
</databaseTypes>
<instances>
<instance name="Test" type="Sql Server"
connectionString="TestString" />
</instances>
<connectionStrings>
<connectionString name="TestString">
<parameters>
<parameter name="database" value="TestDB" />
<parameter name="server" value="TestServer" />
</parameters>
</connectionString>
</connectionStrings>
</enterpriseLibrary.databaseSettings>
</xmlSerializerSection>
</dataConfiguration>
 
M

Martin Honnen

DC said:
in the file listed below I have to programmatically changes some
element values.

I am currently reading the document into an xmldocument, and then
locating the element to modify with xpath, then I change the element
in memory and write the entire document back to disk. I did not find a
more elegant way.

But once a default namespace apeared like in the example below,
everything broke. I certainly have to regard namespaces, but I think
there is no automatic handling in .net? I guess since I read and write
the whole document, I must examine all xmlns attributes and declare
them? Or is there maybe an easy way out?

<dataConfiguration>
<xmlSerializerSection>
<enterpriseLibrary.databaseSettings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
defaultInstance="CmsContent"
xmlns="http://www.microsoft.com/practices/enterpriselibrary/
08-31-2004/data">
<databaseTypes>
<databaseType name="Sql Server" />

Do you know the namespace in advance? Then it is as easy as using an
XmlNamespaceManager and binding a prefix to the namespace URI and using
that XmlNamespaceManager e.g. the following example changes an attribute
of an element in that namespace
http://www.microsoft.com/practices/enterpriselibrary/08-31-2004/data

XmlDocument doc = new XmlDocument();
doc.Load(@"XMLFile1.xml");

XmlNamespaceManager mgr = new
XmlNamespaceManager(doc.NameTable);
mgr.AddNamespace("df",
"http://www.microsoft.com/practices/enterpriselibrary/08-31-2004/data");

XmlElement dbType =
doc.SelectSingleNode("dataConfiguration/xmlSerializerSection/df:enterpriseLibrary.databaseSettings/df:databaseTypes/df:databaseType",
mgr) as XmlElement;
if (dbType != null)
{
dbType.SetAttribute("name", "Oracle");
}

doc.Save(@"XMLFile1.xml");
 
D

DC

Do you know the namespace in advance? Then it is as easy as using an
XmlNamespaceManager and binding a prefix to the namespace URI and using
that XmlNamespaceManager e.g. the following example changes an attribute
of an element in that namespacehttp://www.microsoft.com/practices/enterpriselibrary/08-31-2004/data

             XmlDocument doc = new XmlDocument();
             doc.Load(@"XMLFile1.xml");

             XmlNamespaceManager mgr = new
XmlNamespaceManager(doc.NameTable);
             mgr.AddNamespace("df",
"http://www.microsoft.com/practices/enterpriselibrary/08-31-2004/data");

             XmlElement dbType =
doc.SelectSingleNode("dataConfiguration/xmlSerializerSection/df:enterpriseLibrary.databaseSettings/df:databaseTypes/df:databaseType",
mgr) as XmlElement;
             if (dbType != null)
             {
                 dbType.SetAttribute("name", "Oracle");
             }

             doc.Save(@"XMLFile1.xml");

Thank you, Martin. As a matter of fact, I would not know the default
namespace in advance. The tool is supposed to be able to manipulate
any valid xml configuration file. I guess I have to walk through all
attributes and look out for an xmlns attribute then? There should not
be more than one xmlns attribute without a following :name
declaration, right?

One other problem: in the example above, I guess that the modified xml
file will have df: namespaces for all nodes under the default
namespace decalaration. Therefore, my tool will not only modify the
values specified, but also insert a default namespace name it made up.
I am not sure if this will allow the applications to still read the
configuration settings. I will try the code example with added xmlns
attribute detection anyway.

Regards
DC
 
M

Martin Honnen

DC said:
Thank you, Martin. As a matter of fact, I would not know the default
namespace in advance. The tool is supposed to be able to manipulate
any valid xml configuration file. I guess I have to walk through all
attributes and look out for an xmlns attribute then? There should not
be more than one xmlns attribute without a following :name
declaration, right?

That depends on the XML you receive. It is certainly possible to have e.g.
<foo xmlns="http://example.com/ns1">
<bar xmlns="http://example.com/ns2">
<baz xmlns="http://example.com/ns3">
it is also possible to unset a default namespace declaration e.g.
<foo xmlns="http://example.com/ns1">
<bar xmlns="">
<baz xmlns="http://example.com/ns3">

As for detecting namespace declarations, the DOM implementation in the
..NET framework has two methods GetNamespaceOfPrefix and
GetPrefixOfNamespace exposed on XmlNode. And with an XPathNavigator
(which you can create from any XmlNode with
xmlNodeInstance.CreateNavigator()) you get a method GetNamespacesInScope.

One other problem: in the example above, I guess that the modified xml
file will have df: namespaces for all nodes under the default
namespace decalaration. Therefore, my tool will not only modify the
values specified, but also insert a default namespace name it made up.
I am not sure if this will allow the applications to still read the
configuration settings. I will try the code example with added xmlns
attribute detection anyway.

I am afraid I don't understand what you want to say above. It might help
if you show an example on how you want to manipulate the XML.
 
D

DC

That depends on the XML you receive. It is certainly possible to have e.g..
   <foo xmlns="http://example.com/ns1">
     <bar xmlns="http://example.com/ns2">
       <baz xmlns="http://example.com/ns3">
it is also possible to unset a default namespace declaration e.g.
   <foo xmlns="http://example.com/ns1">
     <bar xmlns="">
       <baz xmlns="http://example.com/ns3">

As for detecting namespace declarations, the DOM implementation in the
.NET framework has two methods GetNamespaceOfPrefix and
GetPrefixOfNamespace exposed on XmlNode. And with an XPathNavigator
(which you can create from any XmlNode with
xmlNodeInstance.CreateNavigator()) you get a method GetNamespacesInScope.


I am afraid I don't understand what you want to say above. It might help
if you show an example on how you want to manipulate the XML.

You did not understand my second question since it comments on a non-
existing problem. In the meantime I tested your code and it writes
back perfect (I assumed adding the namespace manager would make a
difference to saving the file). I have now added the option to
configure a namespace prefix and uri so xml docs with default
namespaces can be processed. I have not checked into the possibilty of
namespace detection yet.

Your posts helped me a lot, thank you once again.

Regards
DC
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top