XML namespace and XmlNamespaceManager c# - c#

I've a little problem..
I'm using XmlNamespaceManager to parse a contex with unknown namespace..
It works really fine but I've a problem...
This is a snapshop of the generated XML
<RecordingConfig b:topic="true" xmlns="http://www.onvif.org/ver10/topics" xmlns:b="http://docs.oasis-open.org/wsn/t-1">
<JobState b:topic="true">
...
</JobState>
</RecordingConfig>
It's ok.. but I'd a little change like this:
<tns1:RecordingConfig b:topic="true" xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:b="http://docs.oasis-open.org/wsn/t-1">
<tns1::JobState b:topic="true">
...
</tns1:JobState>
</tns1:RecordingConfig>
(look the prefix tns1:)
Someone can help me, please?
Thanks in advance

For removing namespace you have to write some 15 lines of code.
Easily you can do if you know the Xmlns then just replace
xdoc is your xml File then,
xdoc.LoadXml(xdoc.OuterXml.Replace("xmlns=\"http://www.onvif.org/ver10/topics\"", ""));
then you can select any node
var node = xdoc.SelectNodes("RecordingConfig/JobState");

Related

How can I ignore the namespace in an XML document in c#?

I'm trying to open a XML file in c#, find a node by attribute name, which is working fine and then displaying the name of an XML attribute in the same node.
My code is simple (as I pinched it from other sources!) and works on my test XML doc. However, when I try it with an actual file it doesn't work. I've been pulling my hair out (not that I have much left) and have discovered it's because of the xmlns attribute in the actual files I'm using. The path to the namespace does not exist.
My code is as follows:
XmlDocument doc = new XmlDocument();
doc.Load(#"c:\deroschedule\test.sym");
var orient = doc.SelectSingleNode("//Attr[#name='Orientation]/#value");
the above code works perfectly when xmlns is not included in the file. However, when xmlns is included the orient variable is null. The xmlns path doesn't exist, when i try to navigate to it in a browser I get a 404 error.
Not sure what a xml namespace is to be honest, but I have thousands of these files and can't manually edit them. Is there an easy way to get C# to overlook the namespace and just pretend it's not there? I've tried with Xpath, but that just blew my mind!
Ok I figured it out for myself. Thought I would post the answer here even though there are thousands of other answers apparently.
Where I went wrong was misunderstanding what the namespace actually does. Anyway I had to use xmlnamespacenmanager to declare the same namespace as in the xml file. Then I had to use the namespace in the query.
XmlDocument doc = new XmlDocument();
doc.Load(#"C:\deroschedule\test6.sym");
XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("ma", "http://www.yournamespaceinfohere.com/");
var orient = doc.SelectSingleNode("//ma:attr[#name='Orientation']/#value", ns);
Now my next challenge is to try and read the bmp from the xml file, should be easy, right?!

find if a code exists in xml, using c#

I am starting to work with xml and I am trying to know if there is a way to search a code in this.
Here you are my xml
<?xml version="1.0" encoding="UTF-8"?>
<doctors_hospital>
<doctor>
<code>1757D</code>
<name>one</name>
</doctor>
<doctor>
<code>1169L</code>
<name>two</name>
</doctor>
... continues xml
</doctors_hospital>
I want to look for the code "aab" using c#, and this is my code..
var document =new XmlDocument();
document.Load("O:\\test\\doctor.xml");
XmlNode doctor;
XmlNode root = document.DocumentElement;
doctor = root.SelectSingleNode("/doctors_hospital/doctor/code='aab'");
I can not do this. any suggestion? thanks
Assuming SelectingSingleNode takes a standard XPath expression, what you want to use is
/doctors_hospital/doctor[code='aab']
This will select the entire doctor node with the matching code value.
I agree with Jim, alternatively you could also use Linq to Xml and do this.
XDocument doc = XDocument.Load(filepath);
var codeExist = doc.Descendants("code").Any(x=>(string)x.Value == "1169L");
Check this Demo

How to change the data within elements in a XML file using C#?

I'm kind of new to XML files in C# ASP.NET. I have a XML in the below format:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Installation>
<ServerIP>192.168.20.110</ServerIP>
<DB_Name>USTCKT1</DB_Name>
<Username>jorame</Username>
<Password>Cru$%e20</Password>
<Table_PreFix>TCK</Table_PreFix>
</Installation>
I need to change the values within each element. For example, when an user clicks I should be able to replace 192.168.20.110 with 192.168.1.12.
How can I accomplish this? Any help will be really appreciated.
You should look at using the methods in the XDocument class. http://msdn.microsoft.com/en-us/library/bb301598.aspx
Specifically look at the methods: Load(string) - to load an XML file, Element() - to access a specific element and Save(string) - to save the XML document. The page on Element() has some sample code which can help.
http://msdn.microsoft.com/en-us/library/system.xml.linq.xcontainer.element.aspx
You can do something like this using the XDocument class:
XDocument doc = XDocument.Load(file.xml);
doc.Element("Installation").Element("ServerIP").Value = "192.168.1.12";
//Update the rest of the elements
doc.Save(file.xml);
More Details
If you run into namespace issues when selecting your elements you will need to include the xml namespace in the XElement selectors eg doc.Element(namspace + "Installation")
In general, you can do it in the following steps:
Create a new XmlDocument object and load the content. The content might be a file or string.
Find the element that you want to modify. If the structure of your xml file is too complex, you can use xpath you find what you want.
Apply your modification to that element.
Update your xml file.
Here is a simple demo:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("file.xml"); // use LoadXml(string xml) to load xml string
string path = "/Installation/ServerIP";
XmlNode node = xmlDoc.SelectSingleNode(path); // use xpath to find a node
node.InnerText = "192.168.1.12"; // update node, replace the inner text
xmlDoc.Save("file.xml"); // save updated content
Hope it's helpful.

Deletion of a single node in xml using c#

My xml file is as follows:
<Default>
<CareSettingName>
<Name>Hosp1/Name>
<Name>Hosp2/Name>
<Name>Hosp3/Name>
<Name>Hosp4/Name>
</CareSettingName>
<DocNames>
<Name>Doc1/Name>
<Name>Doc2/Name>
<Name>Doc3/Name>
</DocNames>
</Default>
With the following code I try to delete Hosp4:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(localXMLfile);
XmlNode node = xmlDoc.SelectSingleNode("/Default/CareSettingName[Name='Hosp4']");
node.ParentNode.RemoveChild(node);
xmlDoc.Save(localXMLfile);
When I run this, it deletes ALL the entries in CareSettingName - not the single one I am looking for. I can't see to find the problem. Can somebody please help me?
Can anybody please help me? Thanks.
It's because you're selecting /Default/CareSettingName (when it contains a Name that equals Hosp4).
Try changing your xpath to:
/Default/CareSettingName/Name[.='Hosp4']

How to prevent blank xmlns attributes in output from .NET's XmlDocument?

When generating XML from XmlDocument in .NET, a blank xmlns attribute appears the first time an element without an associated namespace is inserted; how can this be prevented?
Example:
XmlDocument xml = new XmlDocument();
xml.AppendChild(xml.CreateElement("root",
"whatever:name-space-1.0"));
xml.DocumentElement.AppendChild(xml.CreateElement("loner"));
Console.WriteLine(xml.OuterXml);
Output:
<root xmlns="whatever:name-space-1.0"><loner xmlns="" /></root>
Desired Output:
<root xmlns="whatever:name-space-1.0"><loner /></root>
Is there a solution applicable to the XmlDocument code, not something that occurs after converting the document to a string with OuterXml?
My reasoning for doing this is to see if I can match the standard XML of a particular protocol using XmlDocument-generated XML. The blank xmlns attribute may not break or confuse a parser, but it's also not present in any usage that I've seen of this protocol.
Thanks to Jeremy Lew's answer and a bit more playing around, I figured out how to remove blank xmlns attributes: pass in the root node's namespace when creating any child node you want not to have a prefix on. Using a namespace without a prefix at the root means that you need to use that same namespace on child elements for them to also not have prefixes.
Fixed Code:
XmlDocument xml = new XmlDocument();
xml.AppendChild(xml.CreateElement("root", "whatever:name-space-1.0"));
xml.DocumentElement.AppendChild(xml.CreateElement("loner", "whatever:name-space-1.0"));
Console.WriteLine(xml.OuterXml);
Thanks everyone to all your answers which led me in the right direction!
This is a variant of JeniT's answer (Thank you very very much btw!)
XmlElement new_element = doc.CreateElement("Foo", doc.DocumentElement.NamespaceURI);
This eliminates having to copy or repeat the namespace everywhere.
If the <loner> element in your sample XML didn't have the xmlns default namespace declaration on it, then it would be in the whatever:name-space-1.0 namespace rather than being in no namespace. If that's what you want, you need to create the element in that namespace:
xml.CreateElement("loner", "whatever:name-space-1.0")
If you want the <loner> element to be in no namespace, then the XML that's been produced is exactly what you need, and you shouldn't worry about the xmlns attribute that's been added automatically for you.
Since root is in an unprefixed namespace, any child of root that wants to be un-namespaced has to be output like your example. The solution would be to prefix the root element like so:
<w:root xmlns:w="whatever:name-space-1.0">
<loner/>
</w:root>
code:
XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement( "w", "root", "whatever:name-space-1.0" );
doc.AppendChild( root );
root.AppendChild( doc.CreateElement( "loner" ) );
Console.WriteLine(doc.OuterXml);
If possible, create a serialization class then do:
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlSerializer serializer = new XmlSerializer(yourType);
serializer.Serialize(xmlTextWriter, someObject, ns);
It's safer, and you can control the namespaces with attributes if you really need more control.
I've solved the problem by using the Factory Pattern. I created a factory for XElement objects. As parameter for the instantiation of the factory I've specified a XNamespace object. So, everytime a XElement is created by the factory the namespace will be added automatically. Here is the code of the factory:
internal class XElementFactory
{
private readonly XNamespace currentNs;
public XElementFactory(XNamespace ns)
{
this.currentNs = ns;
}
internal XElement CreateXElement(String name, params object[] content)
{
return new XElement(currentNs + name, content);
}
}
Yes you can prevent the XMLNS from the XmlElement .
First Creating time it is coming : like that
<trkpt lat="30.53597" lon="-97.753324" xmlns="">
<ele>249.118774</ele>
<time>2006-05-05T14:34:44Z</time>
</trkpt>
Change the code : And pass xml namespace
like this
C# code:
XmlElement bookElement = xdoc.CreateElement("trkpt", "http://www.topografix.com/GPX/1/1");
bookElement.SetAttribute("lat", "30.53597");
bookElement.SetAttribute("lon", "97.753324");

Categories