Namespaced nodes of the same name - content of the attributes needed - c#

got this document:
<uniprot xmlns="http://uniprot.org/uniprot" xmlns:xsi="http://www.w3.org/2001/ XMLSchema-instance" xsi:schemaLocation="http://uniprot.org/uniprot http://www.uniprot.org/support/docs/uniprot.xsd">
<entry dataset="Swiss-Prot" created="1986-07-21" modified="2013-10-16" version="88">
<dbReference type="GO" id="GO:0006412">
<property type="term" value="P:translation"/>
<property type="evidence" value="IEA:InterPro"/>
</dbReference>
<dbReference type="HAMAP" id="MF_00294">
<property type="entry name" value="Ribosomal_L33"/>
<property type="match status" value="1"/>
</dbReference>
<dbReference type="InterPro" id="IPR001705">
<property type="entry name" value="Ribosomal_L33"/>
</dbReference>
Right now, I'm using this to grab the inner text of nodes, which works fine...BUT...
XmlDocument XMLdoc = new XmlDocument();
XMLdoc.Load(Datapath);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(XMLdoc.NameTable);
nsmgr.AddNamespace("ns", "http://uniprot.org/uniprot");
String NodeName = XMLdoc.SelectSingleNode("//ns:fullName", nsmgr).InnerText;
... I need to grab the attributes of and whether type's content is GO or not and if so, get the following data of that exact node, namely id and value. Been thinking about and googling for this for several hours and I just lack the knowledge to get anywhere.

I'd suggest using Linq to Xml, I find it a lot easier than XmlDocument and XPath queries, but that is at least partially personal preference.
I'm not quite sure what you mean by the "value" of each element with a type of "GO", but this should get you most of the way there. goTypeNodes will contain a collection of those nodes that have a type of "GO" with their ID and type values, and additionally contains the property elements underneath them, so if by "value" you mean the value of the property elements underneath them, it is trivial to get at that from there.
XNamespace ns = "http://uniprot.org/uniprot";
XDocument doc = XDocument.Load(#"C:\SO\Foo.xml");
var goTypeNodes = from n in doc.Descendants(ns + "dbReference")
select new { Id = n.Attribute("id").Value, Type = n.Attribute("type").Value, Properties = n.Elements()};
By the way, your sample XML is missing closing tags for uniprot and entry.

Actually I managed to solve the problem:
XmlNodeList Testi = XMLdoc.SelectNodes("//ns:dbReference", nsmgr);
foreach (XmlNode xn in Testi)
{
if (xn.Attributes["type"].Value == "GO")
{
String Testilator = xn.Attributes["id"].Value;
String Testilator2 = xn.FirstChild.Attributes["value"].Value;
}
}

Related

C# Create XmlElement from string without xmlns=""

I am building an xml document and I have declared the namespace at the very top.
<Root xmlns="http://www.omg.org/space/xtce" xmlns:xtce="http://www.omg.org/space/xtce" ...>
At some arbitrary level below I want to AppendChild with an element created from a string. My goal is to end up with a document that contains that element without the xmlns AT ALL.
This is the closest I have gotten-
string someElementStr = "<SomeElement name="foo"><SubElement name="bar" /></SomeElement>";
XmlDocumentFragment node = doc.CreateDocumentFragment();
node.InnerXml = someElementStr;
someXmlNodeWithinDoc.AppendChild(node);
This code results in-
<SomeElement name="foo" xmlns="">
<SubElement name="bar" />
</SomeElement>
in the final document.
I use a different construct when I do not have to go from a string to XML-
XmlElement elem = doc.CreateElement("SomeElement", "http://www.omg.org/space/xtce");
elem.SetAttribute("name","foo");
someXmlNodeWithinDoc.AppendChild(elem);
and this yields exactly what I want.
<SomeElement name="foo">
</SomeElement>
I would like to do something line this in my current solution
node.setNamespace("http://www.omg.org/space/xtce") then the document would omit xmlns because it is same as root.
Can someone tell me the idiomatic way to build a document with a single namespace use within, where some elements are stored in the model as a string?
This issue is almost identical to mine except the solution has the luxury of only providing the sub element as a string (everything under "new"). I need the entire element.
string xmlRoot = "<Root xmlns=\"http://www.omg.org/space/xtce\"></Root>";
string xmlChild = "<SomeElement name=\"foo\"><SubElement name = \"bar\"/></SomeElement >";
XDocument xDoc = XDocument.Parse(xmlRoot);
XDocument xChild = XDocument.Parse(xmlChild);
xChild.Root.Name = xDoc.Root.GetDefaultNamespace() + xChild.Root.Name.LocalName;
foreach (XElement xChild2 in xChild.Root.Nodes())
{
xChild2.Name = xDoc.Root.GetDefaultNamespace() + xChild2.Name.LocalName;
}
xDoc.Root.Add(xChild.Root);
string xmlFinal = xDoc.ToString();
This is the solution I ended up with. I did not use #shop350 solution because I didn't want to use XDocument,XElement... Thank you for the feedback though!
// create a fragment which I am going to build my element based on text.
XmlDocumentFragment frag = doc.CreateDocumentFragment();
// here I wrap my desired element in another element "dc" for don't care that has the namespace declaration.
string str = "";
str = "<dc xmlns=\"" + xtceNamespace + "\" ><Parameter name=\"paramA\" parameterTypeRef=\"paramAType\"><AliasSet><Alias nameSpace=\"ID\" alias=\"0001\"/></AliasSet></Parameter></dc>";
// set the xml for the fragment (same namespace as doc)
frag.InnerXml = str;
// let someXmlNodeWithinDoc be of type XmlNode which I determined based on XPath search.
// Here I attach the child element "Parameter" to the XmlNode directly effectively dropping the element <dc>
someXmlNodeWithinDoc.AppendChild(frag.FirstChild.FirstChild);

Reading all root node names in an XML document

I'm sure all the pros out there would find this very trivial but I need a quick solution for this in C#
I'm retrieving an xml schema of a view in share point which looks like this:
<FieldRef Name="LinkTitle"/><FieldRef Name="Author0"/><FieldRef Name="ID"/>
I want to parse this and only retrieve the Name's of each root element in this schema.
currently this is the code I'm working on , need some help with it
String fieldvals = view.ViewFields.SchemaXml.ToString();
XmlDocument reader = new XmlDocument(); ;
reader.LoadXml(fieldvals);
String xpath = "/";
var nodes = reader.SelectNodes(xpath);
foreach (XmlNode childrenNode in nodes)
{
Console.WriteLine(childrenNode.SelectSingleNode("//field1").Value);
}
Apparently, when this piece of code executes, I get an exception saying that more than one root node is present which is true of course .. but I'm not able to figure out the correct code to access every root node and extract it's name!
Wrap your xml fragment within a root node and then you can use linq to xml to retrieve a string array of those names like this:
var xml = XElement.Parse(xmlString);
var names=xml.Elements().Attributes(#"Name").Select(attrib => attrib.Value);
You should wrap your xml in some root node as an XML can have only one Root Node as below :
<FieldRefs>
<FieldRef Name="LinkTitle"/>
<FieldRef Name="Author0"/>
<FieldRef Name="ID"/>
</FieldRefs>
And then your code will execute fine.
String fieldvals = view.ViewFields.SchemaXml.ToString();
XmlDocument reader = new XmlDocument(); ;
reader.LoadXml(fieldvals);
String xpath = "/FieldRefs/FieldRef";
var nodes = reader.SelectNodes(xpath);
foreach (XmlNode childrenNode in nodes)
{
/*Process here*/
}

How to get value of some object in XML string in C#?

I have this XML String :
<RESPONSE>
<SINGLE>
<KEY name="sitename">
<VALUE>Stackoverflow</VALUE>
</KEY>
<KEY name="username">
<VALUE>this value</VALUE>
</KEY>
</SINGLE>
</RESPONSE>
How to get value from Key that name "username" ? I want to get value of "this value" in my code. I try deserialized and any other code but it doesnt work. Please help me, thanks :D
Edit:
I tried using this code :
XDocument doc = XDocument.Load( "myXML.xml" );
var keys = doc.Descendants( "KEY" );
foreach ( var VALUE in keys )
{
Console.WriteLine( VALUE.Value );
}
But how did I get the Value only from KEY that named "Username" ? Thanks :))
You can probably use an xpath to do this. The following is an example XPath that will provide a node with name matching "sitename":
//KEY[#name="sitename"]
You can modify this slightly to find all nodes with a "name" attribute or to just find specific names. For more examples of how to use XPath see the MSDN site for XPath. The following is a snippet of C# code that shows you how to use this XPath (again, you can generalize for whatever XPath you need):
const string example_xml = "<RESPONSE> <SINGLE> <KEY name=\"sitename\"> <VALUE>Stackoverflow</VALUE> </KEY> <KEY name=\"username\"> <VALUE>this value</VALUE> </KEY> </SINGLE> </RESPONSE>";
// load
XmlDocument doc = new XmlDocument();
doc.LoadXml(example_xml);
// Query single or multiple nodes using the XPath, do what you want with this node!
var desiredNode = doc.SelectSingleNode("//KEY[#name=\"sitename\"]");
Best of luck!
For completeness here is a System.Xml.Linq version, with the foreachs and where's being System.Linq for good measure. This basically the questioner's attempt, with a where to filter according to attribute.
const string example_xml = "<RESPONSE> <SINGLE> <KEY name=\"sitename\"> <VALUE>Stackoverflow</VALUE> </KEY> <KEY name=\"username\"> <VALUE>this value</VALUE> </KEY> </SINGLE> </RESPONSE>";
XDocument doc = XDocument.Parse(example_xml);
var keys = doc.Descendants("KEY");
var userKeys = keys.Where(item => item.Attribute("name").Value == "username").ToList();
userKeys.ForEach(item => Console.WriteLine(item.Value));
Lets consider your xml document as XYZ.xml, then you may try below code if you are using C#, below is the example only
XmlDocument Doc = new XmlDocument();
Doc.Load(Server.MapPath(".../xyz.xml"));
XmlNodeList itemList = Doc.DocumentElement.SelectNodes("KEY");
foreach (XmlNode currNode in itemList)
{
string name = string.Empty;
XmlNode item = currNode.SelectSingleNode("KEY");
if(currNode["name"].InnerText == "username")//if you are aware of key name, use this condition
{
name = item.Attributes["name"].Value.ToString(); // or currNode["name"].InnerText;
}
}

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;
}

How can I read specific elements from XML string using XMLREADER in C#

I have XML String:
<GroupBy Collapse=\"TRUE\" GroupLimit=\"30\">
<FieldRef Name=\"Department\" />
</GroupBy>
<OrderBy>
<FieldRef Name=\"Width\" />
</OrderBy>
I am new in C#. I tried to read the Name attribute of the FieldRef element for both elements but I could not. I used XMLElement , is there any way to pick these two values?
Despite the posting of invalid XML (no root node), an easy way to iterate through the <FieldRef> elements is to use the XmlReader.ReadToFollowing method:
//Keep reading until there are no more FieldRef elements
while (reader.ReadToFollowing("FieldRef"))
{
//Extract the value of the Name attribute
string value = reader.GetAttribute("Name");
}
Of course a more flexible and fluent interface is provided by LINQ to XML, perhaps it would be easier to use that if available within the .NET framework you are targeting? The code then becomes:
using System.Xml.Linq;
//Reference to your document
XDocument doc = {document};
/*The collection will contain the attribute values (will only work if the elements
are descendants and are not direct children of the root element*/
IEnumerable<string> names = doc.Root.Descendants("FieldRef").Select(e => e.Attribute("Name").Value);
try this:
string xml = "<GroupBy Collapse=\"TRUE\" GroupLimit=\"30\"><FieldRef Name=\"Department\" /></GroupBy><OrderBy> <FieldRef Name=\"Width\" /></OrderBy>";
xml = "<root>" + xml + "</root>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
foreach (XmlNode node in doc.GetElementsByTagName("FieldRef"))
Console.WriteLine(node.Attributes["Name"].Value);

Categories