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);
Related
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;
I have the following XML:
<T24.MESSAGE>
<TRANSACTION.TYPE>CHEQUE.ON.THEM.AUTH</TRANSACTION.TYPE>
<TRANSACTION.ID>FT14273PKQ14</TRANSACTION.ID>
</T24.MESSAGE>
I am trying to find the TRANSACTION.TYPE element, using the xpath query /TRANSACTION.TYPE. However, this is returning nothing, and I think it is because the element has a period in the name.
Is there a way to escape the period? Though according to the MS reference it isn't needed. http://msdn.microsoft.com/en-us/library/ms256199%28v=vs.110%29.aspx
Edit: I have also tried /T24.MESSAGE/TRANSACTION.TYPE and just TRANSACTION.TYPE and neither work.
Code I use to read it:
byte[] xmlBytes = Encoding.UTF8.GetBytes(strXML);
using (MemoryStream xmlStream = new MemoryStream(xmlBytes))
{
XPathDocument doc = new XPathDocument(XmlReader.Create(xmlStream, xmlReaderSettings));
var navigator = doc.CreateNavigator();
var node = navigator.SelectSingleNode("/TRANSACTION.TYPE"); //null
//...
}
Since you're using namespaces you might try using a namespace agnostic form in your code. It'd look like this
var node = navigator.SelectSingleNode("//*[local-name()='TRANSACTION.TYPE']");
The issue is with your namespace. You'll need to create a XmlNamespaceManager and pass that to your SelectSingleNode call.
In the below I've created a namespace of urn:test:
string strXML = #"<?xml version='1.0'?>
<T24.MESSAGE xmlns=""urn:Test"">
<TRANSACTION.TYPE>CHEQUE.ON.THEM.AUTH</TRANSACTION.TYPE>
<TRANSACTION.ID>FT14273PKQ14</TRANSACTION.ID>
</T24.MESSAGE>";
byte[] xmlBytes = Encoding.UTF8.GetBytes(strXML);
using (MemoryStream xmlStream = new MemoryStream(xmlBytes))
{
XPathDocument doc = new XPathDocument(XmlReader.Create(xmlStream));
var navigator = doc.CreateNavigator();
XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(navigator.NameTable);
//Add the namespaces used. In this instance I'm setting a prefix of "t"
xmlnsManager.AddNamespace("t", "urn:Test");
//pass the XmlNamespaceManager to the call to SelectSingleNode
//the XPath also includes the root element
var node = navigator.SelectSingleNode("//t:T24.MESSAGE/t:TRANSACTION.TYPE", xmlnsManager);
Console.WriteLine(node.Name);
}
This code correctly ouptuts
TRANSACTION.TYPE
This certainly works
string yourXMLString = #"<T24.MESSAGE>
<TRANSACTION.TYPE>CHEQUE.ON.THEM.AUTH</TRANSACTION.TYPE>
<TRANSACTION.ID>FT14273PKQ14</TRANSACTION.ID>
</T24.MESSAGE>";
XDocument xDoc = XDocument.Parse(yourXMLString);
var res = xDoc.Descendants("T24.MESSAGE")
.Elements("TRANSACTION.TYPE");
result: <TRANSACTION.TYPE>CHEQUE.ON.THEM.AUTH</TRANSACTION.TYPE>
I am Working on Visual-studio 2012 in C#.
I want to get the names of total number of templates in a given xslt(Template.xslt) file.
Given below code gives only the first template.
List<string> listTemplates = new List<string>();
XmlDocument xslDoc = new XmlDocument();
xslDoc.Load("Template.xslt");
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xslDoc.NameTable);
nsMgr.AddNamespace("xsl", "http://www.w3.org/1999/XSL/Transform");
XmlAttribute valueOf = (XmlAttribute)xslDoc.SelectSingleNode("/xsl:stylesheet/xsl:template/#name", nsMgr);
Let me know how i get all the template names from an XSLT file.
You can use the below method which uses System.Linq.XElement.
public static IEnumerable<string> GetTemplateNames(string xsltPath)
{
var xsl = XElement.Load(xsltPath);
return xsl.Elements("{http://www.w3.org/1999/XSL/Transform}template")
.Where(temp => temp.Attribute("name") != null)
.Select(temp => temp.Attribute("name").Value);
}
Alternatively, you can do a slight modification in your code to achieve the same.
List<string> listTemplates = new List<string>();
XmlDocument xslDoc = new XmlDocument();
xslDoc.Load("Template.xslt");
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xslDoc.NameTable);
nsMgr.AddNamespace("xsl", "http://www.w3.org/1999/XSL/Transform");
var nameAttributes = xslDoc
.SelectNodes("/xsl:stylesheet/xsl:template/#name", nsMgr)
.Cast<XmlAttribute>();
var names=nameAttributes.Select(n => n.Value);
After having template names, I want to read its param names.
For a particular template I wrote the below code(templateName is the name of the Template in the XSLT file):
XmlNodeList templateParam = (XmlNodeList)xslDoc.SelectNodes("/xsl:stylesheet/xsl:template/[#name = '" + templateName + "']/xsl:param/#name", nsMgr);
It shows an error "Expression must evaluate to a node-set."
What am i missing here?
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
simple question but I've been dinking around with it for an hour and it's really starting to frustrate me. I have XML that looks like this:
<TimelineInfo>
<PreTrialEd>Not Started</PreTrialEd>
<Ambassador>Problem</Ambassador>
<PsychEval>Completed</PsychEval>
</TimelineInfo>
And all I want to do is use C# to get the string stored between <Ambassador> and </Ambassador>.
So far I have:
XmlDocument doc = new XmlDocument();
doc.Load("C:\\test.xml");
XmlNode x = doc.SelectSingleNode("/TimelineInfo/Ambassador");
which selects the note just fine, now how in the world do I get the content in there?
May I suggest having a look at LINQ-to-XML (System.Xml.Linq)?
var doc = XDocument.Load("C:\\test.xml");
string result = (string)doc.Root.Element("Ambassador");
LINQ-to-XML is much more friendly than the Xml* classes (System.Xml).
Otherwise you should be able to get the value of the element by retrieving the InnerText property.
string result = x.InnerText;
The InnerText property should work fine for you.
http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.innertext.aspx
FWIW, you might consider switching API to linq-to-xml (XElement and friends) as IMHO it's a friendly, easier API to interact with.
System.Xml version (NOTE: no casting to XmlElement needed)
var xml = #"<TimelineInfo>
<PreTrialEd>Not Started</PreTrialEd>
<Ambassador>Problem</Ambassador>
<PsychEval>Completed</PsychEval>
</TimelineInfo>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
var node = doc.SelectSingleNode("/TimelineInfo/Ambassador");
Console.WriteLine(node.InnerText);
linq-to-xml version:
var xml = #"<TimelineInfo>
<PreTrialEd>Not Started</PreTrialEd>
<Ambassador>Problem</Ambassador>
<PsychEval>Completed</PsychEval>
</TimelineInfo>";
var root = XElement.Parse(xml);
string ambassador = (string)root.Element("Ambassador");
Console.WriteLine(ambassador);
XmlDocument doc = new XmlDocument();
doc.Load("C:\\test.xml");
XmlNode x = doc.SelectSingleNode("/TimelineInfo/Ambassador");
x.InnerText will return the contents
Try using Linq to XML - it provides a very easy way to query xml datasources - http://msdn.microsoft.com/en-us/library/bb387098%28v=VS.100%29.aspx