Child nodes not accepted - c#

I'm writing on a program in C# that'll take data from a server, write it into a file and then read the file to grab the data contained.
The last part is the problem. I get my XML-file stream and the XML file seems to be fine but except for the root node, my program doesn't accept any child nodes even though in a list it counts all the 700 child nodes. Was checking my spelling, the adressing, the tree... nothing worked so far.
XML Data:
<?xml version="1.0" encoding="UTF-8"?>
<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="2005-03-01" modified="2013-10-16" version="51">
<accession>P69430</accession>
<accession>O65938</accession>
<accession>P27856</accession>
<name>TATA_ECO57</name>
<protein>
<recommendedName>
<fullName>Sec-independent protein translocase protein TatA</fullName>
</recommendedName>
</protein>
program:
Datapath = startupPath + "\\" + Data[0, 0] + ".xml";
XmlDocument XMLdoc = new XmlDocument();
XMLdoc.Load(Datapath);
XmlNodeList xnList = XMLdoc.SelectNodes("//*"); //the list shows all 700 entries so the path etc are correct
var node = XMLdoc.SelectSingleNode("uniprot/entry/protein/recommendedName/fullName").InnerText;
As soon as I try to adress any child node from uniprot, it's just null which drives me mad. Anyone can help please?

Have you tried using the namespace?
XmlDocument doc = new XmlDocument();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ns", "http://uniprot.org/uniprot");
var node = doc.SelectSingleNode("//ns:exampleNode", nsmgr);

Try this one: XmlNode node = doc.SelectSingleNode("//uniprot//entry/protein/recommendedName /fullName");
node.InnerXml;

Related

C# how to read single item in node xml

I have xml file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><SENT_110 xmlns:ns2="http://www.mf.gov.pl/SENT/2017/01/18/STypes.xsd" xmlns="http://www.mf.gov.pl/SENT/2017/01/18/SENT_110.xsd"><SentNumber>SENT20180416000032</SentNumber><KeyNumber><ns2:SenderKey>KS-28YM</ns2:SenderKey><ns2:RecipientKey>KR-52DH</ns2:RecipientKey><ns2:CarrierKey>KD-48WW</ns2:CarrierKey></KeyNumber>
I want to read in separate SenderKey, RecipientKey & CarrierKey.
When i use this code:
XmlTextReader reader = new XmlTextReader(file);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(reader);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ns", xmlDoc.DocumentElement.NamespaceURI);
XmlNodeList nodeList = xmlDoc.SelectNodes("/ns:SENT_110/ns:KeyNumber", nsmgr);
foreach (XmlNode node in nodeList)
{
key = node.InnerText;
MessageBox.Show(key);
}
i've got something like this: KS-28YMKR-52DHKD-48WW, without any separate between key.
How i could read only one key?
Use the following XPath:
"/ns:SENT_110/ns:KeyNumber/*"
It will return all nested nodes to you.
If the structure of the XML is fixed it is rather easy by using XDocument:
var xmlText = "<SENT_110 xmlns:ns2=\"http://www.mf.gov.pl/SENT/2017/01/18/STypes.xsd\" xmlns=\"http://www.mf.gov.pl/SENT/2017/01/18/SENT_110.xsd\"><SentNumber>SENT20180416000032</SentNumber><KeyNumber><ns2:SenderKey>KS-28YM</ns2:SenderKey><ns2:RecipientKey>KR-52DH</ns2:RecipientKey><ns2:CarrierKey>KD-48WW</ns2:CarrierKey></KeyNumber></SENT_110>";
var xml = XDocument.Parse(xmlText);
var nodes = xml.Descendants();
var senderKey = nodes.First(d => d.Name.ToString().EndsWith("SenderKey")).Value;
var recipientKey = nodes.First(d => d.Name.ToString().EndsWith("RecipientKey")).Value;
var carrierKey = nodes.First(d => d.Name.ToString().EndsWith("CarrierKey")).Value;
See HERE for a working snippet. If this is just a part of a bigger XML or the structure can be different maybe some more complex searching is needed.

Insert node in xml document using c#

I was trying to insert an XML node in XML document at a specific position.
This is my xml:
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<readContract xmlns="http://implementation.company.schema.reference">
<ContactNumbers>10158</ContactNumbers>
<productGroups>0085</productGroups>
<indicationBalanceInfo>false</indicationBalanceInfo>
<indicationBlocked>true</indicationBlocked>
</readContract>
</Body>
</Envelope>
And am trying to insert another tag <productGroups>0093</productGroups> below to the tag <productGroups>0085</productGroups>
Expecting like the below:
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<readContract xmlns="http://implementation.company.schema.reference">
<ContactNumbers>10158</ContactNumbers>
<productGroups>0085</productGroups>
<productGroups>0093</productGroups>
<indicationBalanceInfo>false</indicationBalanceInfo>
<indicationBlocked>true</indicationBlocked>
</readContract>
</Body>
</Envelope>
Used the below C# code to achieve it.
XmlDocument doc = new XmlDocument();
string inputxml = this.StServiceCallActivity5.InputEnvelope.InnerXml.ToString();
//Here inputxml contains whole xml document.
string addxml = "<productGroups>0093</productGroups>";
doc.LoadXml(inputxml);
XmlDocumentFragment xmlDocFrag = doc.CreateDocumentFragment();
xmlDocFrag.InnerXml = addxml;
XmlElement parentEle = doc.DocumentElement;
parentEle.AppendChild(xmlDocFrag);
And it returns value like
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<readContract xmlns="http://implementation.company.schema.reference">
<ContactNumbers>10158</ContactNumbers>
<productGroups>0085</productGroups>
<productGroups>0093</productGroups>
<indicationBalanceInfo>false</indicationBalanceInfo>
<indicationBlocked>true</indicationBlocked>
</readContract>
</Body>
<productGroups xmlns="">0093</productGroups>
</Envelope>
Am a newbie to C# code, kindly help me to get the XML doc as expected.
your help is much appreciated.
When you do this:
XmlElement parentEle = doc.DocumentElement;
parentEle.AppendChild(xmlDocFrag);
You're appending the node to the root of the document. You probably wanted to select the actual readContract node that the item is supposed to be appended into. As an example:
XmlNode newNode = doc.CreateNode(XmlNodeType.Element, "productGroup", "");
newNode.InnerText = "something";
XmlNode readContractNode = doc["Envelope"]["Body"]["readContract"];
XmlElement groups = readContractNode["productGroups"];
readContractNode.InsertAfter(newNode, groups);
Of course you'd probably want to handle the case where there are already multiple child productGroup elements, but the idea is the same.
Looks like namespaces are causing the problem. This worked for me:
XmlDocument doc = new XmlDocument();
doc.LoadXml(File.ReadAllText("XMLFile1.xml"));
XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("ns1", "http://schemas.xmlsoap.org/soap/envelope/");
ns.AddNamespace("ns2", "http://implementation.company.schema.reference");
var rootNode = doc.SelectSingleNode("//ns1:Envelope", ns);
var readContractNode = rootNode.FirstChild.FirstChild;
var newNode = doc.CreateNode(XmlNodeType.Element, "productGroups", "http://implementation.company.schema.reference");
newNode.InnerText = "0093";
readContractNode.InsertAfter(newNode, readContractNode.SelectSingleNode("//ns2:productGroups", ns));
Or if you don't fancy namespaces like I me, you can try a bit more "brute-forcy" approach:
XmlDocument doc = new XmlDocument();
doc.LoadXml(File.ReadAllText("XMLFile1.xml"));
var newNode = doc.CreateNode(XmlNodeType.Element, "productGroups", "http://implementation.company.schema.reference");
newNode.InnerText = "0093";
doc.FirstChild.FirstChild.FirstChild.InsertAfter(newNode, doc.FirstChild.FirstChild.FirstChild.FirstChild.NextSibling);
It can be optimized but I think it helps to make the point that root cause is the different namespaces in the document.
You may want to use XmlNode.InsertAfter Method.
public virtual XmlNode InsertAfter(
XmlNode newChild,
XmlNode refChild
)
Where
newChild = The XmlNode to insert
and
refChild = The XmlNode that is the reference node. The newNode is placed after the refNode
Please check this link for information.
And check this link with answer on SO.
P.S.
Always check other answers before posting new question.

stuck on xpath query

I have an xmlnodelist which results in the below snippet
<updi:ProductName xmlns:updi="urn:rosettanet:specification:universal:ProductIdentification:xsd:schema:01.04">Packet Processing Card (PPC) 16GB</updi:ProductName>
<ulc:AlternativeIdentifier xmlns:ulc="urn:rosettanet:specification:universal:Locations:xsd:schema:01.04">
<ulc:Authority>PID</ulc:Authority>
<ulc:Identifier>ASR5K-PPC-K9=</ulc:Identifier>
</ulc:AlternativeIdentifier>
<ulc:AlternativeIdentifier xmlns:ulc="urn:rosettanet:specification:universal:Locations:xsd:schema:01.04">
<ulc:Authority>CPN</ulc:Authority>
<ulc:Identifier />
</ulc:AlternativeIdentifier>
How can I grab the two authority and identifier tags? I tried adding a root element but I have issues with the namespaces. The original namespace declaration is very large.
Well, I doubt there's anything wrong with the XPath queries you've tried - more likely it's the namespaces that are tripping you up. There are a few ways to compensate/deal with this, ranging from "strip out all the namespaces" to using the XmlNamespaceManager - here's an example of that:
void Main()
{
var doc = new XmlDocument();
var namespaceMgr = new XmlNamespaceManager(doc.NameTable);
namespaceMgr.AddNamespace("updi", "urn:rosettanet:specification:universal:ProductIdentification:xsd:schema:01.04");
namespaceMgr.AddNamespace("ulc", "urn:rosettanet:specification:universal:Locations:xsd:schema:01.04");
doc.LoadXml(xml);
var authorityTags = doc.SelectNodes("//ulc:Authority", namespaceMgr);
var identifierTags = doc.SelectNodes("//ulc:Identifier", namespaceMgr);
}
Assuming xml is:
string xml = #"
<ROOT>
<updi:ProductName xmlns:updi=""urn:rosettanet:specification:universal:ProductIdentification:xsd:schema:01.04"">
Packet Processing Card (PPC) 16GB
</updi:ProductName>
<ulc:AlternativeIdentifier xmlns:ulc=""urn:rosettanet:specification:universal:Locations:xsd:schema:01.04"">
<ulc:Authority>PID</ulc:Authority>
<ulc:Identifier>ASR5K-PPC-K9=</ulc:Identifier>
</ulc:AlternativeIdentifier>
<ulc:AlternativeIdentifier xmlns:ulc=""urn:rosettanet:specification:universal:Locations:xsd:schema:01.04"">
<ulc:Authority>CPN</ulc:Authority>
<ulc:Identifier />
</ulc:AlternativeIdentifier>
</ROOT>";
The below will return all four nodes from your sample. I did have to wrap it in a root node for my testing. The | operator allows for the union functionality.
//ulc:AlternativeIdentifier/ulc:Authority | //ulc:AlternativeIdentifier/ulc:Identifier
I tested this using Notepad++ with the XPatherizerNPP plugin, which I highly recommend.
Something like this will do the trick:
XmlDocument doc = new XmlDocument();
doc.Load("YourXmlFile");
foreach (XmlNode node in doc.SelectNodes("//*[local-name() = \"Authority\"]"))
{
Console.WriteLine("Authority: " + node.InnerText);
}
foreach (XmlNode node in doc.SelectNodes("//*[local-name() = \"Identifier\"]"))
{
Console.WriteLine("Identifier: " + node.InnerText);
}
Basically, SelectNodes("//*[local-name() = \"Identifier\"]") tells it to search for node in the xml with that name, regardless of namespace, etc.

Delete a whole Node from an Xml Advertisement file?

I am trying to delete a whole XmlNode which matches a certain condition
The format of my xml file is as follows:
<?xml version="1.0" encoding="utf-8"?>
<Advertisements>
<Ad>
<ImageUrl>image/Hydrangeas.jpg</ImageUrl>
<NavigateUrl>www.google.com</NavigateUrl>
<AlternateText>nbfndbf</AlternateText>
<ID>0</ID>
<Impressions>1</Impressions>
</Ad>
</Advertisements>
My deleting code:
XElement x =
new XElement("Ad",
new XElement("ImageUrl", lblImageURL.Text),
new XElement("NavigateUrl", lblImageURL.Text),
new XElement("AlternateText", lblAlternateText.Text),
new XElement("ID", lblID.Text),
new XElement("Impressions", lblfrequency.Text));
string filepath = Request.PhysicalApplicationPath.ToString() + "Adrotator.xml";
XmlDocument xD = new XmlDocument();
xD.LoadXml(x.ToString());
XmlNode xN = xD.FirstChild;
xN.ParentNode.RemoveChild(xN);
**xD.Save(filepath);**
I am getting an error Invalid XML document. The document does not have a root element.
You can use linq to xml to achieve this here exmple how to remove node where value ID = 0
var q = (from c in doc.Descendants("Advertisements")
from v in c.Elements("Ad")
where (int) v.Element("ID") == 0
select v).Remove();
here is another example using xpath
doc.XPathSelectElement("Advertisements/Ad[ID = 0]").Remove();
You create a new XDocument (doc) with the following code:
XDocument doc = XDocument.Load(filepath);
Is there something in the Xml file (with a root element)? Also, you don't seem to use doc in the code, so it's at least not required.

Reading Elements within a Namespace

I have an XML file that looks like:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="https://www.someurl.com/somefile.xslt"?>
<AutoInsuranceClaim xmlns="http://www.someurl.com/schemas/AutoInsuranceClaim">
<Identification>
<BaseOwner>3</BaseOwner>
<BaseType>ABC123</BaseType>
<BaseTypeRef>471038341757</BaseTypeRef>
</Identification>
</AutoInsuranceClaim>
and I'm trying to read the Identification node. Here's my code:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"..\..\Data.xml");
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ns", "http://www.someurl.com/schemas/AutoInsuranceClaim");
XmlNodeList nodeList = xmlDoc.SelectNodes(#"/ns:AutoInsuranceClaim/Identification", nsmgr);
Console.WriteLine("There are {0} nodes...", nodeList.Count);
I know I should get a least 1 value. My understanding of .NET XML parsing is that if you have a default namespace with no prefix, you have to create your own namespace. But this should have returned 1.
If not, what am I missing?
I might be grasping at straws here, but shouldn't you be namespacing both entities in your xpath expression?
XmlNodeList nodeList = xmlDoc.SelectNodes(#"/ns:AutoInsuranceClaim/ns:Identification", nsmgr);
XElement root = XElement.Load("Data.xml");
var identifications = root.Descendants()
.Where(x => x.Name.LocalName == "Identification")
.ToList()
The problem is that you're trying to find an Identification node without a namespace, but it will have defaulted to the same namespace as the parent due to the xmlns=... part. Try this:
var nodeList = xmlDoc.SelectNodes("/ns:AutoInsuranceClaim/ns:Identification",
nsmgr);
Having tried it myself, it printed a count of 1.
Personally I'd use LINQ to XML instead though, which makes namespace easier handling:
XDocument doc = XDocument.Load(#"..\..\Data.xml");
XNamespace ns = "http://www.someurl.com/schemas/AutoInsuranceClaim";
var nodes = doc.Root.Elements(ns + "Identification");

Categories