Get schemalocation in root Node using XmlDocument using c# - c#

i have to fill up an XML file from a DATA TABLE ,my problem is that i have to get the schemaLocation in the root node ,for this i use the code below ,then i have this result,and i dont know where is p1 coming from

In your resulting XML, p1 is a namespace. The code you have posted (in a screenshot) is defining the namespace "xsi", I'm not sure why your result is generating p1 unless you are renaming xsi somewhere that is not shown.
XmlDocument doc = new XmlDocument();
XmlDeclaration declaire = doc.CreateXmlDeclaration("1.0", "utf-8", null);
XmlElement rootnode = doc.CreateElement("BMECAT");
doc.InsertBefore(declaire, doc.DocumentElement);
doc.AppendChild(rootnode);
rootnode.SetAttribute("version", "2005");
XmlAttribute atr = doc.CreateAttribute("xsi", "schemaLocation", "http://www.w3.org/2001/XMLSchema-instance");
atr.Value = "http://www.adlnet.org/xsd/adlcp.vlp3";
rootnode.SetAttributeNode(atr);
rootnode.Attributes.Append(atr);
In your code:
XmlAttribute atr = doc.CreateAttribute("xsi", "schemaLocation", "http://www.w3.org/2001/XMLSchema-instance");
"xsi" is the name of the namespace it generates, you can control it there. This results in:
<?xml version="1.0" encoding="utf-8"?>
<BMECAT version="2005" xsi:schemaLocation="http://www.adlnet.org/xsd/adlcp.vlp3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
I'm not sure your code matches the result file you provided. When I ran the code, I get "xsi" as expected. If I set "xsi" to null there, it uses a default name, which in my case was d1p1. All instances of "xsi" were replaced with "d1p1". This makes me believe that code might be slightly different from what generated your result. I don't know where "d1p1" came from, it's likely a generated default namespace. This seems like a common default (Remove "d1p1" namespace prefix in DataContractSerializer XML output). In your provided code, if you change "xsi" to "p1" you would get your result.
I might suggest using this method instead:
How to Add schemaLocation attribute to an XML document
Here you would use the accepted answer against your XmlElement rootnode.
XmlElement.SetAttributeValue (localname, prefix, namespace, value)

Please try this code and let me know whether this helped you or not.
Particularly in this code i parse XML file and get the root element:
Then use it to select all attributes named schemaLocation. There is only one, so you can use SelectSingleNode:
The variable
schemaLocationAttribute
Contanins Value attribute through which you can get actual value.
XmlReader xmlReader = XmlReader.Create("MyXML.xml");
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(xmlReader);
XmlElement root = xmlDocument.DocumentElement;
XmlNode schemaLocationAttribute = root.SelectSingleNode("//#*[local-name()='schemaLocation']");
//Single schema value
string schemaValue = schemaLocationAttribute.Value;
//If you have multiple values in your schema
//you have to store it inside of array
string[] multipleShcemavalues = schemaLocationAttribute.Value.Split(null);
//And you have to choose whuickelement you want to use
string chooosendShcema = multipleShcemavalues[1]; //For example

Related

How to get innertext from xml node that has '\' along with other characters when fetched as string

Hi i am facing an issue extracting innertext from an xml script saved as varchar2 in my oracle database.
While fetching i am getting the xml in the following format:
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<SpecificAction xmlns=\"http://www.xyz.com/schemas/core/caut\">action to take</SpecificAction>"
the following xml is fetched using the code below:
instance.cautDescription = records.GetStringOrDefault("SPEC_ACTION");
the field SPEC_ACTION is of VARCHAR2(4000 BYTE) type.
due to the presence of \ character in the xml from database i am not able to extract the inner text withing the Tag. I tried the following code for fetching the inner text:
string s = instance.cautDescription;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(s);
XmlNode specificAction = xmlDoc.DocumentElement.SelectSingleNode("/SpecificAction");
string specific = specificAction.InnerText;
xmlString = specificAction.InnerText;
return xmlString;
My code is returning null can this be avoided if so how , any support would be really helpful.
This is classic problem when working with XML having default namespace. In XML, when you have default namespace (namespace without prefix, like xmlns="...."), all elements without prefix considered in default namespace. But in XPath, all elements without prefix considered has no namespace. To bridge this different paradigm, you need to declare a prefix that point to default namespace URI and use it in XPath :
var nsManager = new XmlNamespaceManager(xmlDoc.NameTable);
nsManager.AddNamespace("ns", xmlDoc.DocumentElement.NamespaceURI);
XmlNode specificAction = xmlDoc.DocumentElement.SelectSingleNode("/ns:SpecificAction", nsManager);
string specific = specificAction.InnerText;
Since the "SpecificAction" node has a namespace, you will need to supply a namespace manager.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(s);
XmlNamespaceManager ns = new XmlNamespaceManager(xmlDoc.NameTable);
ns.AddNamespace("xyz", "http://www.xyz.com/schemas/core/caut");
XmlNode specificAction = xmlDoc.SelectSingleNode("/xyz:SpecificAction", ns);
return specificAction.InnerText;

Reading XML to get value of a tag c#

I have my XML as
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<recordsDirectory>F:/model_RCCMREC/</recordsDirectory>
<transferDirectory>F:/model_RCCMrecTransfered/</transferDirectory>
<logDirectory>F:/model_RCCMLOG/</logDirectory>
<connectionstring>Data Source=192.168.1.7;Initial Catalog=RCCMdb;User ID=genesys;Password=genesys</connectionstring>
<table>RCCMrec</table>
<DBdestination>
<val1>ANI</val1>
<val2>DNIS</val2>
<val3>Date</val3>
<val4>Time</val4>
<val5>ConnId</val5>
<val6>UUID</val6>
<val7>EmployeeId</val7>
<val8>AgentDN</val8>
</DBdestination>
</configuration>
I need the value of the recordsDirectory tag.
I tried this,
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load("C:/Users/yachna/Desktop/RCCM_TOOL/configRCCM.xml");
string bvalue = xmldoc.SelectSingleNode("recordsDirectory").InnerText.ToString();
But got an error saying
Object reference not set to an instance of an object.
Yes, SelectSingleNode("recordsDirectory") will return null, because you're applying that XPath to the document itself - which doesn't have a recordsDirectory element at the top level, it has a configuration element. You want:
xmldoc.SelectSingleNode("configuration/recordsDirectory")
Or go via the root element:
xmldoc.DocumentElement.SelectSingleNode("recordsDirectory")
(Or you can fetch all descendant elements call recordsDirectory, etc. There are plenty of options here.)
Personally I'd suggest changing to use LINQ to XML if you can, as it's a simpler way of using XML, IMO. It's not too bad in the code you've given so far, but as you do more things with XmlDocument you'll run into it being a bit of a pain - relatively speaking, anyway.
You should also consider separating the "fetching the node" from getting the text, so you can validate that you've found the one you want:
XmlNode node = xmldoc.DocumentElement.SelectSingleNode("recordsDirectory");
if (node != null)
{
// Use it
}
else
{
// No such node. What do you want to do?
}
Try this one in your SelectSingleNode
XmlNode node = doc.SelectSingleNode("/configuration/recordsDirectory");
string s = node.InnerText.ToString();
Hi To read the recordsDirectory tag you need to do :
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load("C:/Users/yachna/Desktop/RCCM_TOOL/configRCCM.xml");
string bvalue = xmldoc.SelectSingleNode("configuration/recordsDirectory").InnerText.ToString();
It will work perfactly

Modifying an XML node with user-provided namespace and node value

It has taken a while, but I have finally been able to modify an XML document based on user input for the namespace and node name:
string nodeName = "DefinitionName"; // this is really provided by the user
string namespace = "http://schemas.datacontract.org/2004/07/Xxx.Session"; // also user-provided
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(taskResolved.XmlPathAndFileName);
XmlElement rootElement = xmlDocument.DocumentElement;
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(xmlDocument.NameTable);
namespaceManager.AddNamespace("snuh", namespace); // hard-coded prefix, grrr...
XmlNodeList xmlNodes;
xmlNodes = rootElement.SelectNodes("//snuh:" + nodeName, namespaceManager);
I feel like I'm doing something wrong because I have to hard-code a prefix (snuh). I could try and choose a prefix, like snuh, that I can hope will never appear in a document, but that isn't foolproof. Another option is to use a GUID for a prefix, but this just seems like a hack work-around. Am I missing something? Is there a better way?
The top of the XML doc looks like this:
<?xml version="1.0" encoding="utf-8"?>
<SessionStateInfo xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="1"
z:Type="Xxx.SessionStateInfo"
z:Assembly="Xxx.Common, Version=6.2.0.0, Culture=neutral, PublicKeyToken=null"
xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"
xmlns="http://schemas.datacontract.org/2004/07/Xxx.Session">
<CoaterNumber>25</CoaterNumber>
<DefinitionName z:Id="2">TwoLineMarkerDefinition</DefinitionName>
<EnableManualMode>true</EnableManualMode>
If you want to simply select the first DefinitionName node.
You may write
XmlNode node = rootElement[nodeName, namespace];
and if you want the whole list:
XmlNodeList nodeList = rootElement.GetElementsByTagName(nodeName, namespace);
What about using the XPath local-name() and namespace-uri() functions?
string xpath = string.Format("//*[local-name()='{0}' and namespace-uri()='{1}']", nodeName, namespace);
xmlNodes = rootElement.SelectNodes(xpath);
Don't know if those functions are supported in XmlDocument though, haven't tested it.

Get nodes from xml files

How to parse the xml file?
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>link</loc>
<lastmod>2011-08-17T08:23:17+00:00</lastmod>
</sitemap>
<sitemap>
<loc>link</loc>
<lastmod>2011-08-18T08:23:17+00:00</lastmod>
</sitemap>
</sitemapindex>
I am new to XML, I tried this, but it seems to be not working :
XmlDocument xml = new XmlDocument(); //* create an xml document object.
xml.Load("sitemap.xml");
XmlNodeList xnList = xml.SelectNodes("/sitemapindex/sitemap");
foreach (XmlNode xn in xnList)
{
String loc= xn["loc"].InnerText;
String lastmod= xn["lastmod"].InnerText;
}
The problem is that the sitemapindex element defines a default namespace. You need to specify the namespace when you select the nodes, otherwise it will not find them. For instance:
XmlDocument xml = new XmlDocument();
xml.Load("sitemap.xml");
XmlNamespaceManager manager = new XmlNamespaceManager(xml.NameTable);
manager.AddNamespace("s", "http://www.sitemaps.org/schemas/sitemap/0.9");
XmlNodeList xnList = xml.SelectNodes("/s:sitemapindex/s:sitemap", manager);
Normally speaking, when using the XmlNameSpaceManager, you could leave the prefix as an empty string to specify that you want that namespace to be the default namespace. So you would think you'd be able to do something like this:
// WON'T WORK
XmlDocument xml = new XmlDocument();
xml.Load("sitemap.xml");
XmlNamespaceManager manager = new XmlNamespaceManager(xml.NameTable);
manager.AddNamespace("", "http://www.sitemaps.org/schemas/sitemap/0.9"); //Empty prefix
XmlNodeList xnList = xml.SelectNodes("/sitemapindex/sitemap", manager); //No prefixes in XPath
However, if you try that code, you'll find that it won't find any matching nodes. The reason for this is that in XPath 1.0 (which is what XmlDocument implements), when no namespace is provided, it always uses the null namespace, not the default namespace. So, it doesn't matter if you specify a default namespace in the XmlNamespaceManager, it's not going to be used by XPath, anyway. To quote the relevant paragraph from the Official XPath Specification:
A QName in the node test is expanded into an expanded-name using the
namespace declarations from the expression context. This is the same
way expansion is done for element type names in start and end-tags
except that the default namespace declared with xmlns is not used: if
the QName does not have a prefix, then the namespace URI is null (this
is the same way attribute names are expanded). It is an error if the
QName has a prefix for which there is no namespace declaration in the
expression context.
Therefore, when the elements you are reading belong to a namespace, you can't avoid putting the namespace prefix in your XPath statements. However, if you don't want to bother putting the namespace URI in your code, you can just use the XmlDocument object to return the URI of the root element, which in this case, is what you want. For instance:
XmlDocument xml = new XmlDocument();
xml.Load("sitemap.xml");
XmlNamespaceManager manager = new XmlNamespaceManager(xml.NameTable);
manager.AddNamespace("s", xml.DocumentElement.NamespaceURI); //Using xml's properties instead of hard-coded URI
XmlNodeList xnList = xml.SelectNodes("/s:sitemapindex/s:sitemap", manager);
Sitemap has 2 sub nodes "loc" and "lastmod". The nodes that you are accessing are "name" and "url". that is why you are not getting any result. Also in your XML file the last sitemap tag is not closed properly with a corresponding Kindly try xn["loc"].InnerText and see if you get the desired result.
I would definitely use LINQ to XML instead of the older XmlDocument based XML API. You can accomplish what you are looking to do using the following code. Notice, I changed the name of the element that I am trying to get the value of to 'loc' and 'lastmod', because this is what is in your sample XML ('name' and 'url' did not exist):
XElement element = XElement.Parse(XMLFILE);
IEnumerable<XElement> list = element.Elements("sitemap");
foreach (XElement e in list)
{
String LOC= e.Element("loc").Value;
String LASTMOD = e.Element("lastmod").Value;
}

Getting single node from xml document c#

I'm trying to get channel element from this document.
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://purl.org/rss/1.0/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
xmlns:admin="http://webns.net/mvcb/"
xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
<channel rdf:about="http://developers.slashdot.org/">
<title>Slashdot: Developers</title>
<link>http://developers.slashdot.org/</link>
...
I think it's in the default namespace, which seems to be "http://purl.org/rss/1.0/" so I tried like this:
XmlNamespaceManager nsmsgr = new XmlNamespaceManager(rssDoc.NameTable);
nsmsgr.AddNamespace(String.Empty, "http://purl.org/rss/1.0/");
XmlNode root = rssDoc.DocumentElement;
XmlNode channel = rssDoc.SelectSingleNode("channel", nsmsgr);
I doesn't work. XmlNode channel stays null.
You can't add it as Empty.
http://msdn.microsoft.com/en-us/library/system.xml.xmlnamespacemanager.addnamespace.aspx
The prefix to associate with the
namespace being added. Use
String.Empty to add a default
namespace. Note If the
XmlNamespaceManager will be used for
resolving namespaces in an XML Path
Language (XPath) expression, a prefix
must be specified. If an XPath
expression does not include a prefix,
it is assumed that the namespace
Uniform Resource Identifier (URI) is
the empty namespace. For more
information about XPath expressions
and the XmlNamespaceManager, refer to
the XmlNode.SelectNodes and
XPathExpression.SetContext methods.XPathExpression.SetContext methods.
So just add the default prefix as "default", then use "/*/default:channel".
Working code:
var nsmsgr = new XmlNamespaceManager(rssDoc.NameTable);
nsmsgr.AddNamespace("default", "http://purl.org/rss/1.0/");
var root = rssDoc.DocumentElement;
var channel = rssDoc.SelectSingleNode("/*/default:channel", nsmsgr);
The above code works, but it's got a hardcoded URI and it uses a "cheat" to avoid dealing with the root node. Here's a cleaner, more general solution:
var nsmsgr = new XmlNamespaceManager(rssDoc.NameTable);
var root = rssDoc.DocumentElement;
nsmsgr.AddNamespace("default", root.GetAttribute("xmlns"));
nsmsgr.AddNamespace("rdf", root.GetAttribute("xmlns:rdf"));
var channel = rssDoc.SelectSingleNode("/rdf:RDF/default:channel", nsmsgr);
Just do:
XmlNode channel = rssDoc.SelectSingleNode(#"//channel");
XmlElement root = rssDoc.DocumentElement;
XmlNode channel = root.SelectSingleNode("/channel");
That will get you the channel node, you can then reference, Attributes, Value, InnerXML, FirstChild etc to pull the data from that node.
*edit: should have been XmlElement instead of Node

Categories