In my web application, I am using NHibernate configured by an xml file (nhibernate.cfg.xml). I need to read the connection string from that file in my C# code. My code is working, but I don't like it (in particular the foreach!) and I would like to query the xml file in a straight manner. I have tried to query it with link, but I always get null nodes.
Here is the cfg file:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">
NHibernate.Connection.DriverConnectionProvider
</property>
<property name="connection.driver_class">
NHibernate.Driver.SqlClientDriver
</property>
<property name="connection.connection_string">
Server=LEG\SQL12;initial catalog=DVR;user id=daniele;pwd=s;
</property>
<property name="dialect">
NHibernate.Dialect.MsSql2008Dialect
</property>
</session-factory>
</hibernate-configuration>
and here it is my C# code:
public static String GetConnectionString()
{
if (String.IsNullOrEmpty(_connectionString))
{
XElement root = XElement.Load("hibernate.cfg.xml");
var sessionFactoryNode = root.Elements().FirstOrDefault(); // session-factory
if (sessionFactoryNode != null)
{
var properties = sessionFactoryNode.Elements();
foreach (var property in properties)
{
if (property.Attribute("name").Value == "connection.connection_string")
_connectionString = property.Value.Trim();
}
}
}
return _connectionString;
}
How can I obtain the same result querying the xml?
XElement root = XElement.Load("hibernate.cfg.xml");
var connString = root.Descendants("property")
.Where(p => (string) p.Attribute("name") == "connection.connection_string")
.Select(p => (string) p)
.First();
Related
Loading this XML works
<?xml version="1.0" encoding="utf-8" ?>
<export>
<document ID="uuuid_1">
<Property Name="PersonName" Value="bob"></Property>
<Property Name="FileName" Value="bob.tif">
<Reference Link="company\export\uuuid_1_423_bob.tif"/>
</Property>
<Property Name="FileName" Value="bob.txt">
<Reference Link="company\export\uuuid_1_123_bob.txt"/>
</Property>
<Property Name="FileName" Value="bob.tif">
<Reference Link="company\export\uuuid_1_123_bob.tif"/>
</Property>
</document>
<document ID="uuuid_2">
<Property Name="PersonName" Value="mary"></Property>
<Property Name="FileName" Value="mary.tif">
<Reference Link="company\export\uuuid_2_456_mary.tif"/>
</Property>
<Property Name="FileName" Value="mary.txt">
<Reference Link="company\export\uuuid_2_567_mary.txt"/>
</Property>
</document>
</export>
with that method
static void XmlLoader(string xml_path)
{
Console.WriteLine("Loading " + xml_path);
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(xml_path);
XmlNodeList nodes_document = xmldoc.SelectNodes("/export/document");
foreach (XmlNode nd in nodes_document)
{
string Id = nd.Attributes["ID"].Value.ToString();
string name = nd.SelectSingleNode("//Property[#Name='PersonName']/#Value").InnerText;
XmlNodeList files = nd.SelectNodes("//Property[#Name='FileName'][contains(#Value,'.tif')]/Reference/#Link");
Console.WriteLine(files.ToString());
}
}
The XmlNodeList inside the iteration of documents brings back a list of ALL tifs in the XML not only the ones from the nd Node.
How would I correctly use Xpath to select a list inside the nd element?
Just remove "//" from SelectNodes and SelectSingleNode. The double slash is parsing the complete xml
static void XmlLoader(string xml_path)
{
Console.WriteLine("Loading " + xml_path);
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(xml_path);
XmlNodeList nodes_document = xmldoc.SelectNodes("/export/document");
foreach (XmlNode nd in nodes_document)
{
string Id = nd.Attributes["ID"].Value.ToString();
string name = nd.SelectSingleNode("Property[#Name='PersonName']/#Value").InnerText;
XmlNodeList files = nd.SelectNodes("Property[#Name='FileName'][contains(#Value,'.tif')]/Reference/#Link");
Console.WriteLine(files.ToString());
}
}
I have next XML file:
<root>
<location id='IBM'>
<property name='locale' value='en-EN' />
<property name='path' value='c:\program files\IBM' />
<property name='option' value='licence' />
<package kind='offering' name='IBM tools'>
<property name='cic.name' value='IBM Studio'/>
<property name='cic.version' value='13.4'/>
</package>
</location>
<location id='Microsoft'>
<property name='locale' value='en-EN' />
<property name='path' value='c:\program files\MS' />
<property name='option' value='licence' />
<package kind='offering' name='Microsoft'>
<property name='cic.name' value='Windows XP'/>
<property name='cic.version' value='10.3.2'/>
</package>
</location>
</root>
How I can get this values from cic.name and cic.version inside that XML structure:
IBM Studio
13.4
Windows Xp
10.3.2
I have tried this
XElement roots = XElement.Load(#"C:\test.xml");
foreach (var i in roots.Descendants("location"))
{
Console.WriteLine(i.Attribute("id").Value);
}
But I get only:
IBM
Microsoft
Thank you!
Here is the solution
var doc = XDocument.Load(yourXmlFilePath);
var packages = doc.Descendants("package")
.Select(p => new
{
Name = p.Elements("property")
.SingleOrDefault(i => i.Attribute("name")?.Value == "cic.name")
?.Attribute("value")
?.Value,
Version = p.Elements("property")
.SingleOrDefault(i => i.Attribute("name")?.Value == "cic.version")
?.Attribute("value")
?.Value
}).ToList();
var result = names.Select(i => string.Format("{0} {1}", i.Name, i.Version)).ToList();
//result: "IBM Studio 13.4"
// "Windows XP 10.3.2"
Your code only looks for id attributes on location elements.
If you want the cic.name and cic.version values, you'll have to include those in your query instead.
var results =
from package in doc.Descendants("package")
select new
{
Name = (string) package.Elements("property")
.Where(x => (string) x.Attribute("name") == "cic.name")
.Attributes("value")
.Single(),
Version = (string) package.Elements("property")
.Where(x => (string) x.Attribute("name") == "cic.version")
.Attributes("value")
.Single(),
};
See this fiddle for a demo.
Try something like this
foreach (var Locations in roots.Descendants("location"))
{
foreach (var item in Locations.Descendants("package"))
{
Console.WriteLine(item.Attribute("id").Value);
}
}
i need some help. i've got xml like this:
<?xml version='1.0' encoding='utf-8'?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
</session-factory>
</hibernate-configuration>
and i want to read property NAME and value (value is between
i have done something like this
XPathNodeIterator iterator = nav.Select("/nh:hibernate-configuration/nh:session-factory/nh:property/#name", manager);
XPathNodeIterator iterator2 = nav.Select("/nh:hibernate-configuration/nh:session-factory/nh:property", manager);
while (iterator.MoveNext() && iterator2.MoveNext())
{
var name = iterator.Current.Value;
var property = iterator2.Current.Value;
}
but it is possible to have only one iterator in that case which i could use to get name and property ?
You can use only the 2nd iterator and use GetAttribute() to read name attribute value :
XPathNodeIterator iterator2 = nav.Select("/nh:hibernate-configuration/nh:session-factory/nh:property", manager);
while (iterator2.MoveNext())
{
var navigator = iterator.Current;
var name = navigator.GetAttribute("name","");
var property = navigator.Value;
}
Anyway, the entire task can be much simpler using XmlDocument, or using LINQ-to-XML as demonstrated below :
var doc = XDocument.Load("path_to_your_xml.xml");
XNamespace d = "urn:nhibernate-configuration-2.2";
foreach(var prop in doc.Descendants(d+"property")
{
var name = (string)prop.Attribute("name");
var property = (string)prop;
}
I am trying to load an XML file onto my GUI using a TreeView control.
However, I am using a proprietary layout for my XML file.
The XML is structured like this:
<ConfiguratorConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Section>
<Class ID="Example" Name="CompanyName.Example" Assembly="Example.dll">
<Interface>
<Property Name="exampleProperty1" Value="exampleValue" />
<Property Name="exampleProperty2" Value="exampleValue" />
<Property Name="exampleProperty3" Value="exampleValue" />
</Interface>
</Class>
</Section>
</ConfiguratorConfig>
I'd like the output to be structured like:
Class "Example"
Property "exampleProperty1"
Property "exampleProperty2"
Property "exampleProperty3"
I'm totally new to using XML. I've been searching the web for the past few hours, and none of the results have helped. Some have come close, but perhaps properties won't show up, or node's names won't display, etc.
I'm writing in c# in Visual Studio 2005.
Thanks for the help!
You can iterate through nodes using XmlDocument, you can put this demo in a Main method of a console application:
string xml = #"<ConfiguratorConfig xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
<Section>
<Class ID=""Example"" Name=""CompanyName.Example"" Assembly=""Example.dll"">
<Interface>
<Property Name=""exampleProperty1"" Value=""exampleValue"" />
<Property Name=""exampleProperty2"" Value=""exampleValue"" />
<Property Name=""exampleProperty3"" Value=""exampleValue"" />
</Interface>
</Class>
</Section></ConfiguratorConfig>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
foreach (XmlNode _class in doc.SelectNodes(#"/ConfiguratorConfig/Section/Class"))
{
string name = _class.Attributes["ID"].Value;
Console.WriteLine(name);
foreach (XmlElement element in _class.SelectNodes(#"Interface/Property"))
{
if (element.HasAttribute("Name"))
{
string nameAttributeValue = element.Attributes["Name"].Value;
Console.WriteLine(nameAttributeValue);
}
}
}
If you're using version of .NET higher than 3.0 you can use XDocument class (recommended if you can choose).
XDocument xdoc = XDocument.Parse(xml);
foreach (XElement _class in xdoc.Descendants("Class"))
{
string name = _class.Attribute("ID").Value;
Console.WriteLine(name);
foreach (XElement element in _class.Descendants("Property"))
{
XAttribute attributeValue = element.Attribute("Name");
if (attributeValue != null)
{
string nameAttributeValue = attributeValue.Value;
Console.WriteLine(nameAttributeValue);
}
}
}
Need help in parsing the following XML. I am a newbie to Linq to XML.
I want to parse all picture data in a single objects array, and I dont seem to find a way,
Here is a sample xml,
<Object type="System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="Form1" children="Controls">
<Object type="System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="PictureBox1" children="Controls">
<Property name="TabIndex">0</Property>
<Property name="Size">206, 152</Property>
<Property name="ImageLocation">C:\Documents and Settings\Administrator\Desktop\logo2w.png</Property>
<Property name="Location">41, 68</Property>
<Property name="TabStop">False</Property>
<Property name="Name">PictureBox1</Property>
<Property name="DataBindings">
<Property name="DefaultDataSourceUpdateMode">OnValidation</Property>
</Property>
</Object>
<Object type="System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" name="PictureBox2" children="Controls">
<Property name="TabIndex">0</Property>
<Property name="Size">206, 152</Property>
<Property name="ImageLocation">C:\Documents and Settings\Administrator\Desktop\logo2w.png</Property>
<Property name="Location">42, 68</Property>
<Property name="TabStop">False</Property>
<Property name="Name">PictureBox2</Property>
<Property name="DataBindings">
<Property name="DefaultDataSourceUpdateMode">OnValidation</Property>
</Property>
</Object>
</Object>
I want to access the value as PictureObjects[0].Location = 41, 68, PictureObjects[1].Location = 42, 68 etc, Can I do it?
I saw several samples where I can create such objects based on the node name, and not based on the nodes attribute value? C# LINQ with XML, cannot extract multiple fields with same name into object
Can someone guide or let me know if its feasible?
You can start with this, code below just select TabIndex and Size properties, obviously adding other would not be a tricky:
XDocument xdoc = XDocument.Load(#"path to a file or use text reader");
var tree = xdoc.Descendants("Object").Skip(1).Select(d =>
new
{
Type = d.Attribute("type").Value,
Properties = d.Descendants("Property")
}).ToList();
var props = tree.Select(e =>
new
{
Type = e.Type,
TabIndex = e.Properties
.FirstOrDefault(p => p.Attribute("name").Value == "TabIndex")
.Value,
Size = e.Properties
.FirstOrDefault(p => p.Attribute("name").Value == "Size")
.Value
});