XML SelectSingleNode where sibling = 'something' - c#

Consider the following XML:
<SomeRoot>
<SomeElement>
<SomeThing>25</SomeThing>
<SomeOther>Cat</SomeOther>
</SomeElement>
<SomeElement>
<SomeThing>46</SomeThing>
<SomeOther>Dog</SomeOther>
</SomeElement>
<SomeElement>
<SomeThing>83</SomeThing>
<SomeOther>Bat</SomeOther>
</SomeElement>
<SomethingElse>Unrelated to the SomeElements above</SomethingElse>
</SomeRoot>
I want to select SomeThing where SomeOther = 'Cat'. The following C# code throws a null reference exception:
xmlDoc = new XmlDocument();
this.path = path;
// Path is passed elsewhere
Console.WriteLine(xmlDoc.SelectSingleNode("/SomeRoot/SomeElement/SomeThing[../SomeOther='Cat']").InnerText);
What is the correct XPath syntax to use here?

You are missing the load
var xmlDoc = new XmlDocument();
xmlDoc.Load(path);
Console.WriteLine(xmlDoc.SelectSingleNode("/SomeRoot/SomeElement/SomeThing[../SomeOther='Cat']").InnerText);

Here's what I did and it works;
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(#"<SomeRoot><SomeElement><SomeThing>25</SomeThing><SomeOther>Cat</SomeOther></SomeElement></SomeRoot>");
var x = xDoc.SelectSingleNode("/SomeRoot/SomeElement/SomeThing[../SomeOther= 'Cat']").InnerText;

You can avoid using any reverse axis:
/*/SomeElement[SomeOther='Cat']/SomeThing

Related

Changing value in dtsConfig file from c# code

I have a dtsConfig file with configuration for ssis package variable User::Quote_ID:
<Configuration ConfiguredType="Property"
Path="\Package.Variables[User::Quote_ID].Properties[Value]"
ValueType="String"><ConfiguredValue>77777</ConfiguredValue></Configuration>
I want to change this value from c# code:
XmlDocument xDoc = new XmlDocument();
xDoc.Load(#"\\MyServer\DataFiles$\...\MyConfigFile.dtsConfig");
XmlNode xFile = xDoc.SelectSingleNode("User::Quote_ID");
xFile.Value = quote_ID.ToString();
xDoc.Save(#"\\MyServer\DataFiles$\...\MyConfigFile.dtsConfig");
xDoc = null;
It gives me an error on the third line of my code (XmlNode...):
‘User::Quote_ID’ has an invalid token
What is wrong?
Chris! Your code helped me a lot! In my case it did not work thought. I ran the application in debug mode and I could see that xDoc.Load... opens the right file, but it did not execute foreach loop. The property listOfConfigurationNodes had Count = 0. I checked my xml file again and found that it has outer node and all nodes inside this outer node. So I changed your code
XmlNodeList listOfConfigurationNodes = xDoc.SelectNodes("Configuration");
I made:
XmlNode XMLOuterNode = xDoc.SelectSingleNode("DTSConfiguration");
XmlNodeList listOfConfigurationNodes = XMLOuterNode.SelectNodes("Configuration");
This code works fine for my particular case. Thanks a lot!!!
The node name is "Configuration". Within that, you have an attribute called "Path", whose value is "\Package.Variables[User::Quote_ID].Properties[Value]".
I'm not sure what you need to do in your code, but here is an example of one way to go about making changes in that value:
XmlDocument xDoc = new XmlDocument();
xDoc.Load(#"\\MyServer\DataFiles$\...\MyConfigFile.dtsConfig");
XmlNode xFile = xDoc.SelectSingleNode("Configuration");
xFile.Attributes["Path"].Value = xFile.Attributes["Path"].Value.Replace("User::Quote_ID", "newValue");
xDoc.Save(#"\\MyServer\DataFiles$\...\MyConfigFile.dtsConfig");
xDoc = null;
The above example will change \Package.Variables[User::Quote_ID].Properties[Value] to \Package.Variables[newValue].Properties[Value].
Updated Example
This will replace the 77777 value with quote_ID.ToString() (I'm assuming the 55555 is in there) for the first node (for all nodes, remove break;) where the 'Path' is \Package.Variables[User::Quote_ID].Properties[Value].
XmlDocument xDoc = new XmlDocument();
xDoc.Load(#"\\MyServer\DataFiles$\...\MyConfigFile.dtsConfig");
XmlNodeList listOfConfigurationNodes = xDoc.SelectNodes("Configuration");
foreach (XmlNode node in listOfConfigurationNodes)
{
if (node.Attributes["Path"].Value == #"\Package.Variables[User::Quote_ID].Properties[Value]")
{
node.SelectSingleNode("ConfiguredValue").InnerText = quote_ID.ToString();
break;
}
}
xDoc.Save(#"\\MyServer\DataFiles$\...\MyConfigFile.dtsConfig");
xDoc = null;

C# and XPath - getting attribute?

I'm open to all suggestions, but prefer no looping if possible. I'm trying to get the num-found attribute from this XML into a variable, but it's coming back NULL and I can't figure out why:
xmlStringGoesHere is this below:
Code:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlStringGoesHere);
int intNumFound = Convert.ToInt32(xmlDoc.SelectSingleNode("/orcid-message/orcid-search-results/#num-found").Value);
I'd like to use SelectSingleNode since it's one line of code. Someone suggested doing this below, but neither one of these work. Furthermore, is there a way to do this without all the "local-name" crap bloating up the code?
object intNumFound = xmlDoc.SelectSingleNode("/*[local-name() = 'orcid-message']/*[local-name() = 'orcid-search-results']");
object intNumFound = xmlDoc.SelectSingleNode("/*[local-name() = 'orcid-message']/*[local-name() = 'orcid-search-results']/#num-found]");
The problem is there are no elements named orcid-message or orcid-search-results; the xmlns in the XML makes it so you have to qualify those names. Here's how you include namespaces in your query:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlStringGoesHere);
var nsMgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsMgr.AddNamespace("o", "http://www.orcid.org/ns/orcid");
var attribute = xmlDoc.SelectSingleNode(
"/o:orcid-message/o:orcid-search-results/#num-found",
nsMgr);
int intNumFound = Convert.ToInt32(attribute.Value);
This seems to work:
XDocument xdoc = XDocument.Parse(xmlStringGoesHere);
int num = Int32.Parse(xdoc.Root.Elements().Where(p => p.Name.LocalName == "orcid-search-results").Attributes().Where(a => a.Name.LocalName == "num-found").First<XAttribute>().Value);

parse xml that contain colon

I have this XML text:
<test:solution xmlns:test="http://www.test.com/">
<script/>
<test:question>
<test:param name="name1">value 1</test:param>
<test:param name="name2"> value 2</test:param>
</test:question>
</test:solution>
when I run my application that contains those lines:
XmlDocument doc = new XmlDocument();
doc.Load(xmlUrl);
XmlNode testQuestions = doc.SelectSingleNode("/test:solution/test:question");
//XmlNodeList testParamNodeList = testQuestions.SelectNodes("test:param");
It give an error, I know that the error come from the colons, but I don't know how to resolve it.
Thanks for help
try this:
XmlDocument doc = new XmlDocument();
doc.Load(PATH);
XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("test", "http://www.test.com/");
XmlNode node = doc.SelectSingleNode("//test:solution//test:question", ns);

Reading attribute of an XML file

I have this XML file, I can read all the the nodes
<?xml version="1.0" encoding="UTF-8"?>
<cteProc xmlns="http://www.portalfiscal.inf.br/cte" versao="1.04">
<CTe xmlns="http://www.portalfiscal.inf.br/cte">
<infCte versao="1.04" ID="CTe3512110414557000014604"></infCte>
</CTe>
</cteProc>
I have tried reading this using C#
string chavecte;
string CaminhoDoArquivo = #"C:\Separados\13512004-procCTe.xml";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(CaminhoDoArquivo); //Carregando o arquivo
chavecte = xmlDoc.SelectSingleNode("infCTe")
.Attributes.GetNamedItem("Id").ToString();
but something is wrong with this code.
If you want to use Linq To Xml
var xDoc = XDocument.Load(CaminhoDoArquivo);
XNamespace ns = "http://www.portalfiscal.inf.br/cte";
var chavecte = xDoc.Descendants(ns+"infCte").First().Attribute("id").Value;
PS: I am assuming your xml's invalid line is as
<infCte versao="1.04" id="CTe3512110414557000014604"></infCte>
replace
chavecte = xmlDoc.SelectSingleNode("infCTe").Attributes.GetNamedItem("Id").Value;
with
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ab", "http://www.portalfiscal.inf.br/cte");
chavecte = xmlDoc.SelectSingleNode("//ab:infCte", nsmgr)
.Attributes.GetNamedItem("Id").Value;
I've also noticed that infCte doesn't have the ID attribute properly defined in your xml
Another possible solution is:
string CaminhoDoArquivo = #"C:\Separados\13512004-procCTe.xml";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(CaminhoDoArquivo); //Carregando o arquivo
// Select the node you're interested in
XmlNode node = xmlDoc.SelectSingleNode("/cteProc/CTe/infCte");
// Read the value of the attribute "ID" of that node
string chavecte = node.Attributes["ID"].Value;

Parsing XML in C# from stream

I've tried several methods, from Linq to loading the data to an XML document, but i can't seem to be able to return the result that i need.
here's the example XML:
<serv:message xmlns:serv="http://www.webex.com/schemas/2002/06/service" xmlns:com="http://www.webex.com/schemas/2002/06/common" xmlns:event="http://www.webex.com/schemas/2002/06/service/event"><serv:header><serv:response><serv:result>SUCCESS</serv:result><serv:gsbStatus>PRIMARY</serv:gsbStatus></serv:response></serv:header><serv:body><serv:bodyContent xsi:type="event:createEventResponse" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><event:sessionKey>11111111</event:sessionKey><event:guestToken>111111111111111111111</event:guestToken></serv:bodyContent></serv:body></serv:message>
And, here's what i've tried to do:
StreamReader reader = new StreamReader(dataStream);
XmlDocument doc = new XmlDocument();
doc.LoadXml(reader.ReadToEnd());
XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
XmlNamespaceManager ns2 = new XmlNamespaceManager(doc.NameTable);
XmlNamespaceManager ns3 = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("serv", "http://www.webex.com/schemas/2002/06/service");
ns2.AddNamespace("com", "http://www.webex.com/schemas/2002/06/common");
ns3.AddNamespace("event", "http://www.webex.com/schemas/2002/06/service/event");
XmlNode node = doc.SelectSingleNode("result",ns);
Yet, for some reason i cannot ever seem to return the actual result, which should be either 'SUCCESS' or 'FAILURE' based on the actual xml above.
How can i do this?
your xpath query is not correct.
try this one :
XmlNode node = doc.SelectSingleNode("//serv:result",ns);
or
XmlNode node = doc.SelectSingleNode("serv:message/serv:header/serv:response/serv:result",ns);
This works:
XDocument doc = XDocument.Load(#"test.xml");
XNamespace serv = "http://www.webex.com/schemas/2002/06/service";
var result = doc.Descendants(serv + "result").First().Value;

Categories