Want to find a specific node in xml - c#

Currently, I have the xml as the following:
<Node_Parent>
<Column name="ColA" value="A" />
<Column name="ColB" value="B" />
<Column name="ColC" value="C" />
</Node_Parent>
How to get value B at ColB? I tried to use XmlDocument.SelectSingleNode("Node_Parent"), but I cannot access to ColB?
If I change to <ColB value="B" />, I can use XmlDocument.SelectSingleNode("Node_Parent/ColB").Attributes["value"].Value, but the xml format doesn't look good?
Thanks.

You need to write an XPath query in the SelectSingleNode:
var value = doc.SelectSingleNode(
"Node_Parent/Column[#name = 'ColB']"
).Attributes["value"].Value;
For more info on the XPath query language, see http://www.w3schools.com/xpath.
Good luck!

Related

Getting Logger Name into Excel file with NLog

Thanks to Rolf's comment in this question:
NLog in C# with severity AND categories
I am able to record to a text file the category of log message (such as "Thermal" or "Database" or "Mechanical". I'm doing this simply by passing a name to the "GetLogger" method.
public MainWindow()
{
InitializeComponent();
var logger = NLog.LogManager.GetCurrentClassLogger();
logger.Info("Hello World");
(NLog.LogManager.GetLogger("Database")).Info("Here is a DB message");
(NLog.LogManager.GetLogger("Thermal")).Info("Here is a Thermal message");
}
The text file looks like this:
2018-05-13 17:40:47.7442|INFO|NLogExperiments.MainWindow|Hello World
2018-05-13 17:40:50.3404|INFO|Database|Here is a DB message
2018-05-13 17:40:50.3404|INFO|Thermal|Here is a Thermal message
which is pretty good. I might ask in a seperate question how to reformat it.
Now I would like to get these messages into a CSV (Excel) file. I'm using:
<target name="excelfile" xsi:type="File" fileName="nLog.csv" archiveAboveSize="50000000" archiveNumbering="Sequence" maxArchiveFiles="3">
<layout xsi:type="CsvLayout">
<!-- Layout Options -->
<column name="time" layout="${longdate}" />
<column name="level" layout="${level}"/>
<column name="name" layout="${name}"/>
<column name="message" layout="${message}" />
<column name="codeLine" layout="${event-context:item=codeLine}" />
</layout>
</target>
but the output is only:
time,level,name,message,codeLine
2018-05-13 17:40:47.7442,Info,,Hello World,
2018-05-13 17:40:50.3404,Info,,Here is a DB message,
2018-05-13 17:40:50.3404,Info,,Here is a Thermal message,
This isn't surprising. I used "name" as a guess.
What is the field in GetLogger called?
More generally, how do I know all the options I can put in the CSV layout?
Finally, is there a good tutorial on using NLog with CSV? I haven't found one.
Thanks,
Dave
What is the field in GetLogger called?
You're looking for ${logger} - see ${logger} docs
More generally, how do I know all the options I can put in the CSV layout?
You could use all layout renderers, see the list with all layout renderers
For options for the CSV formating, see CsvLayout docs

//#attrib vs //name/#attrib in C#

On the XML below, I'm using the SelectSingleNode of XmlDocument to pull out the result value.
evtASxml.SelectSingleNode(#"//#value").Value
returns the value of the first "value."
evtASxml.SelectSingleNode(#"//Result/#value").Value
raises a null exception.
Could someone explain what's going on?
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-CAPI2" Guid="{f00f00-f00-f00f00-f00-f00f00f00}" />
<EventID>30</EventID>
<Version>0</Version>
<Level>2</Level>
<Task>30</Task>
<Opcode>0</Opcode>
<Keywords>0x4000000000000001</Keywords>
<TimeCreated SystemTime="2012-04-08T23:43:37.573242200Z" />
<EventRecordID>4828</EventRecordID>
<Correlation ActivityID="{f00f00-f00-f00-f00-f00f00f00f00}" />
<Execution ProcessID="7512" ThreadID="3220" />
<Channel>Microsoft-Windows-CAPI2/Operational</Channel>
<Computer>Matt-Seven</Computer>
<Security UserID="S-f00-f00-f00-f00f00f00-f00f00f00-f00f00f00-f00f00" />
</System>
<UserData>
<CertVerifyCertificateChainPolicy>
<Policy type="CERT_CHAIN_POLICY_SSL" constant="4" />
<Certificate fileRef="f00f00f00f00f00f00f00f00f00f00f00.cer" subjectName="www.example.com" />
<CertificateChain chainRef="{f00f00-f00-f00-f00-f00f00f00f00}" />
<Flags value="0" />
<SSLAdditionalPolicyInfo authType="server" serverName="example.com">
<IgnoreFlags value="0" />
</SSLAdditionalPolicyInfo>
<Status chainIndex="0" elementIndex="0" />
<EventAuxInfo ProcessName="iexplore.exe" />
<CorrelationAuxInfo TaskId="{f00f00-f00-f00-f00-f00f00f00f00}" SeqNumber="4" />
<Result value="800B010F">The certificate's CN name does not match the passed value.</Result>
</CertVerifyCertificateChainPolicy>
</UserData>
</Event>
Numeric values from my event log replaced with f00.
Just guessing, but I think you want //*[#value], and not //#value
The reason for this problem is that the XML document is in a default namespace.
Selecting elements by name when they are in a default namespace is the most FAQ in XPath.
Xpath treats any unprefixed element name as belonging to "no namespace". In your case no Result element exists that is in "no namespace" (all elements are in the "http://schemas.microsoft.com/win/2004/08/events/event" namespace) and thus no node is selected.
In C# it is recommended that you provide an XmlNamespaceManager as the second argument of SelectSingleNode() -- just use the appropriate overload.
Use:
evtASxml.SelectSingleNode(#"//x:Result/#value", yourXmlNamespaceManager).Value
where the association of "x" to the "http://schemas.microsoft.com/win/2004/08/events/event" namespace has been added to yourXmlNamespaceManager using the AddNamespace() method.

What is the best method to manipulate xml files?

I want to manipulate XML files.
...
<Document Id="1091">
<Indexes>
<Index Name="MODD" Value="aaa" />
<Index Name="DDAT" Value="bbb" />
<Index Name="CDAT" Value="ccc" />
<Index Name="MDAT" Value="ddd" />
<Index Name="DOCN" Value="eee" />
<Index Name="STAT" Value="fff" />
...
</Indexes>
</Document>
<Document Id="2088">
...
I have retrieve the value of some index randomly. I would avoid the loop on all the indexes. What is the tool you advise me to use and why?
load the file as a text file and use RegEx
load the xml file and use XPath
load the xml file and use Linq to Xml
generate the classes with xsd.exe or xsd2code
another approach
I'd go with LinqToXml. Good syntax and easy to use!

How I Update Value To Xml File?

can i assign value to some element of xml file.my xml file format may be like this
<Object type="TextBox">
<Property name="Size">94, 20</Property>
<Property name="Name">TextBox1</Property>
<Property name="Location">70, 30</Property>
<Property name="TabIndex">1</Property>
<Property name="Text">This Is Text Box One.</Property>
</Object>
<Object type="TextBox">
<Property name="Size">94, 20</Property>
<Property name="Name">TextBox2</Property>
<Property name="Location">70, 70</Property>
<Property name="TabIndex">3</Property>
<Property name="Text">This Is Text Box Two.</Property>
</Object>
<Object type="Label">
<Property name="Size">94, 20</Property>
<Property name="Name">Label1</Property>
<Property name="Location">10, 110</Property>
<Property name="TabIndex">2</Property>
<Property name="Text">This Is Label One.</Property>
</Object>
<Object type="TextBox">
<Property name="Size">94, 20</Property>
<Property name="Name">TextBox3</Property>
<Property name="Location">70, 110</Property>
<Property name="TabIndex">4</Property>
<Property name="Text">This Is Text Box Three.</Property>
</Object>
and,i want to update text value of textbox2 to "This Is Update Text".
Is there any way to do like this?I use c#.net 2008.give me right way,please.
Regards
indi
The XmlDocument will do what you need:
http://support.microsoft.com/kb/301233
Just read the document in an XmlDocument after which you have to find the node, which is probably at a path somewhere similar to:
//Object[#type="textbox"][1]/Property[#name="Text"]
Just put that in an XmlNode object and update it's InnerText (I think).
I haven't tested it, but it should be something like this.
First you need to parse XML file using DOM parser, update the value using your DOM parser update function and then save/export XML back. You should let us know what language you use and we will give you links to most popular parsers.
There is a standard way of dealing with XML in almost any modern programming language; there is probably a one-line answer to your question in the documentation for your language. A 10-second Google search found me "Reading and Writing XML in C#"
On the Button click write this code
string sStartupPath = Application.StartupPath; //the path of ~/bin/debug/
XmlTextWriter objXmlTextWriter = new XmlTextWriter(sStartupPath + #"\selected.xml", null);
objXmlTextWriter.Formatting = Formatting.Indented;
objXmlTextWriter.WriteStartDocument();
objXmlTextWriter.WriteStartElement("TEST");
objXmlTextWriter.WriteStartElement("Name");
objXmlTextWriter.WriteStartAttribute("Surname"); //Attribute "Name"
objXmlTextWriter.WriteString("patel"); //Attribute Value
objXmlTextWriter.WriteEndAttribute();
objXmlTextWriter.WriteString(txtname.Text);
objXmlTextWriter.WriteEndElement(); //End of Name Element
objXmlTextWriter.WriteStartElement("Age") ;
objXmlTextWriter.WriteString(txtage.Text);
objXmlTextWriter.WriteEndElement(); //End of Age element
objXmlTextWriter.WriteEndElement();
objXmlTextWriter.Flush();
objXmlTextWriter.Close();
MessageBox.Show("The following file has been successfully created\r\n"
+ sStartupPath
+ #"\selected.xml", "XML", MessageBoxButtons.OK,
MessageBoxIcon.Information);
//It will create selected.xml file in to your project/bin/debug folder..
The out put of the xml file will be like this
value of txtName.text=ABC
value of txtAge.text=XYZ
<?xml version="1.0"?>
<TEST>
<Name Surname="patel">ABC</Name>
<Age>XYZ</Age>
</TEST>
Hope this will Help.

Select latest group by in nhibernate

I have Canine and CanineHandler objects in my application. The CanineHandler object has a PersonID (which references a completely different database), an EffectiveDate (which specifies when a handler started with the canine), and a FK reference to the Canine (CanineID).
Given a specific PersonID, I want to find all canines they're currently responsible for. The (simplified) query I'd use in SQL would be:
Select Canine.*
from Canine
inner join CanineHandler on(CanineHandler.CanineID=Canine.CanineID)
inner join
(select CanineID,Max(EffectiveDate) MaxEffectiveDate
from caninehandler
group by CanineID) as CurrentHandler
on(CurrentHandler.CanineID=CanineHandler.CanineID
and CurrentHandler.MaxEffectiveDate=CanineHandler.EffectiveDate)
where CanineHandler.HandlerPersonID=#PersonID
Edit: Added mapping files below:
<class name="CanineHandler" table="CanineHandler" schema="dbo">
<id name="CanineHandlerID" type="Int32">
<generator class="identity" />
</id>
<property name="EffectiveDate" type="DateTime" precision="16" not-null="true" />
<property name="HandlerPersonID" type="Int64" precision="19" not-null="true" />
<many-to-one name="Canine" class="Canine" column="CanineID" not-null="true" access="field.camelcase-underscore" />
</class>
<class name="Canine" table="Canine">
<id name="CanineID" type="Int32">
<generator class="identity" />
</id>
<property name="Name" type="String" length="64" not-null="true" />
...
<set name="CanineHandlers" table="CanineHandler" inverse="true" order-by="EffectiveDate desc" cascade="save-update" access="field.camelcase-underscore">
<key column="CanineID" />
<one-to-many class="CanineHandler" />
</set>
<property name="IsDeleted" type="Boolean" not-null="true" />
</class>
I haven't tried yet, but I'm guessing I could do this in HQL. I haven't had to write anything in HQL yet, so I'll have to tackle that eventually anyway, but my question is whether/how I can do this sub-query with the criterion/subqueries objects.
I got as far as creating the following detached criteria:
DetachedCriteria effectiveHandlers = DetachedCriteria.For<Canine>()
.SetProjection(Projections.ProjectionList()
.Add(Projections.Max("EffectiveDate"),"MaxEffectiveDate")
.Add(Projections.GroupProperty("CanineID"),"handledCanineID")
);
but I can't figure out how to do the inner join. If I do this:
Session.CreateCriteria<Canine>()
.CreateCriteria("CanineHandler", "handler", NHibernate.SqlCommand.JoinType.InnerJoin)
.List<Canine>();
I get an error "could not resolve property: CanineHandler of: OPS.CanineApp.Model.Canine". Obviously I'm missing something(s) but from the documentation I got the impression that should return a list of Canines that have handlers (possibly with duplicates). Until I can make this work, adding the subquery isn't going to work...
I've found similar questions, such as Only get latest results using nHibernate but none of the answers really seem to apply with the kind of direct result I'm looking for.
Any help or suggestion is greatly appreciated.
Joining to a derived table, CurrentHandler in your example, won't work in HQL the last time I checked. Try mapping a stored procedure that lets you write whatever SQL you like. Here's what a mapped stored procedure looks like:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="S2.BP.NHSupport" namespace="S2.BP.Model">
<sql-query name="spGoGetMyDogs" callable="true">
<return-scalar column="PersonID" type="int" />
exec spGoGetMyDogs #PersonID=:personID
</sql-query>
</hibernate-mapping>
Then you can pass your PersonID parameter in and have NH map the results back to your objects with a transformer like so:
public IEnumerable<Canine> LetTheDogsOut(int personID) {
return nhSession.GetNamedQuery("spGoGetMyDogs")
.SetInt32("personID", personID)
.SetResultTransformer(Transformers.AliasToBean(typeof(Canine)))
.List<Canine>();
}

Categories