Xdocument throws error while XMLdocument loads sucessfully the same xml string - c#

The existing Project loads the XMLDocument from a string transactionXML which is like
\n\t<Transaction>
\n\t\t<TransactionId>6109</TransactionId>
n\t\t<TransactionType>ClaimsCorrespondenceEvent
</TransactionType>\n\t\t<TransactionStatus>
The below code loads xml sucessfully:
document.LoadXml(transactionXML);
but the below code fails and gives exception of invalid character referring to the \n\t etc.
XDocument.Load(transactionXML);
I need to use XDocument as I am using the method Descendants of XDocument which is not available in XMLDocument.
Please is there a way to load the above string by using XDocument. Alternatively how do I use XMLdocument to get all the nodes along with the child with node name "Transaction"
The example XML would be :
<Transactions>
<Transaction>
<Version> 1 </Version>
<Id> 2 </Id>
</Transaction>
<Transaction>
<Version> 2 </Version>
<Id> 3 </Id>
</Transaction>
<Transaction>
<Version> 3 </Version>
<Id> 4 </Id>
</Transaction>
</Transactions>
and I want separate XML for the node Transaction along with its child elements like :
Ist XML set
<Transaction>
<Version> 1 </Version>
<Id> 2 </Id>
</Transaction>
2nd XMl set
<Transaction>
<Version> 2 </Version>
<Id> 3 </Id>
</Transaction>
3rd XMl set
<Transaction>
<Version> 3 </Version>
<Id> 4 </Id>
</Transaction>
Please if some one could let me know how to go about.

For XDcoument, to load xml from a string, you need to use Parse not Load; Load accepts a file path and not an xml string, try:
var xml = XDocument.Parse(transactionXML);
http://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument(v=vs.110).aspx

Related

Start reading from last value in xml

I have this kind of xml file. Root node is Sim and there are multiple "test" subnodes. Also each "test" has an instructor. Finally each instructor has own name,surname and rank values.
<Sim>
<Test ID="1" Description="test1" Date="17/01/2023">
<Instructor Num="1">
<Name>instructor1</Name>
<Surname></Surname>
<Rank></Rank>
</Instructor>
</Test>
<Test ID="2" Description="test2" Date="16/01/2023">
<Instructor Num="22">
<Name>instructor22</Name>
<Surname></Surname>
<Rank></Rank>
</Instructor>
</Test>
</Sim>
With xelement.load, the test ids of this file are read as they are in the file. I want xelement.load to read after test ids are sorted from largest to smallest. How can i do this? instructor part is also included in second code.
<Sim>
<Test ID="3" Description="test3" Date="18/01/2023"></Test>
<Test ID="2" Description="test2" Date="17/01/2023"></Test>
<Test ID="1" Description="test1" Date="16/01/2023"></Test>
</Sim>
Try with XDocument and LINQ
var xDoc = XDocument.Parse(File.ReadAllText("XMLFile2.xml"));
var elements = xDoc.Descendants("Test").OrderByDescending(x=> Convert.ToInt16(x.Attribute("ID").Value));

Nhibernate - xml column not well formed

I have some XML snippets that I store via NHibernate (3.2.0.4000) in a SQL Server database. The table column is defined as XML. Storing and Updating of the XML is working, but in the database I am missing the first node with the encoding and version information.
C# object, inner XML:
<?xml version="1.0" encoding="utf-16"?>
<RsSn>
<Layermapping xmlns="someNamespace">
<Layer layerName="0" layerDescription="5876548" />
<Layer layerName="1" layerDescription="5876549" />
</Layermapping>
</RsSn>
SQL Server Profiler when the data is inserted:
declare #p6 xml
set #p6=convert(xml,
N'<RsSn><Layermapping xmlns="someNamespace">
<Layer layerName="0" layerDescription="5876548"/>
<Layer layerName="1" layerDescription="5876549"/>
</Layermapping>
</RsSn>'
)
The <?xml version="1.0" encoding="utf-16"?> element is missing!
Content of SQL server column (via SSMS studio):
<RsSn>
<Layermapping xmlns="someNamespace">
<Layer layerName="0" layerDescription="5876548" />
<Layer layerName="1" layerDescription="5876549" />
</Layermapping>
</RsSn>
NHibernate Configuration (part of mapping file)
<class name="SnippetEntity" table="tblSnippet">
<id name="SnippetPK" column="SnippetPK" type="Int64">
<generator class="native" />
</id>
<property name="ResourceData" column="ResourceData" type="NHibernate.Type.XmlDocType"/>
</class>
I am not allowed to update the NHibernate assembly.
Is this the correct type that I am using in the mapping file?
Is there some other configuration I have to use so the document is stored "well formed" in the database?
The top <?xml version="1.0" encoding="utf-16"?> construct is called XML prolog. It is not mandatory to have it. XML is well-formed without it.
SQL Server stores XML as Unicode (utf-16). There is no other encoding. That's why SQL Server strips the prolog when it exists in XML.

How to select a value depending on 2 attributes from separate nodes using XPath in C#?

So,
I have an XML file like the following structure,
<Root>
<Parent StoreDate="2014-12-31" Type="1">
<Child1>2014-01-31</Child1>
<Child2 TimePeriod="M1">
<GrandChild1>-4.58849</GrandChild1>
<GrandChild2>288</GrandChild2>
</Child2>
</Parent>
<Parent StoreDate="2014-12-31" Type="1">
<Child1>2014-02-28</Child1>
<Child2 TimePeriod="M1">
<GrandChild1>4.58015</GrandChild1>
<GrandChild2>284</GrandChild2>
</Child2>
</Parent>
<Parent StoreDate="2014-12-31" Type="1">
<Child1>2014-03-31</Child1>
<Child2 TimePeriod="M4">
<GrandChild1>-0.65693</GrandChild1>
<GrandChild2>284</GrandChild2>
</Child2>
</Parent>
<Parent StoreDate="2014-12-31" Type="3">
<Child1>2014-03-31</Child1>
<Child2 TimePeriod="M1">
<GrandChild1>-5.65693</GrandChild1>
<GrandChild2>2334</GrandChild2>
</Child2>
</Parent>
</Root>
I want to select all GrandChild1, if attribute [#Type] of Parent is 1 and attribute [#TimePeriod] of Child2 is M1.
I've loaded root in an XElement named xElement. Then, I'm using
IEnumerable<XElement> elements = xElement.XPathSelectElements("(/Parent[#Type='1'] | /Parent[Child2/#TimePeriod='M1'])/Child2/GrandChild1");
This supposed to select only the 1st and 2nd GrandChild1 from the above XML file. Instead it is selecting all GrandChild1. What am I doing wrong?
I've tried using 'and' instead of '|' in the code. But it's not working at all and throwing exception.
Any suggestions guys?
Thanks in advance.
EDIT:
I also want to select Child1 with the same condition. What do I need to do?
EDIT: Adding code to select Child1 after the question was changed.
Code to select Grand Child1
You can use //Parent[#Type='1']/Child2[#TimePeriod='M1']/GrandChild1
Child 1 Selection XPath: (One way to do)
//Parent[#Type='1']/Child2[#TimePeriod='M1']/../Child1

Unable to use xpath as expected on document

I have the following XML document
<?xml version="1.0" encoding="utf-8"?>
<GovTalkMessage xmlns="http://www.govtalk.gov.uk/CM/envelope">
<EnvelopeVersion>2.0</EnvelopeVersion>
<Header>
<MessageDetails>
<Class>
</Class>
<Qualifier>request</Qualifier>
<Function>submit</Function>
<CorrelationID />
<Transformation>
</Transformation>
<GatewayTest>0</GatewayTest>
</MessageDetails>
<SenderDetails>
<IDAuthentication>
<SenderID>
</SenderID>
<Authentication>
<Method>clear</Method>
<Role>principal</Role>
<Value></Value>
</Authentication>
</IDAuthentication>
</SenderDetails>
</Header>
<GovTalkDetails>
<Keys>
<Key Type="TaxOfficeNumber">
</Key>
<Key Type="TaxOfficeReference">
</Key>
</Keys>
<TargetDetails>
<Organisation>IR</Organisation>
</TargetDetails>
<ChannelRouting>
<Channel>
<URI>
</URI>
<Product></Product>
<Version>
</Version>
</Channel>
<timestamp>
</timestamp>
</ChannelRouting>
</GovTalkDetails>
<Body>
<IRenvelope xmlns="">
<IRheader>
<Keys>
<Key Type="TaxOfficeNumber">
</Key>
<Key Type="TaxOfficeReference">
</Key>
</Keys>
<PeriodEnd>
</PeriodEnd>
<DefaultCurrency>GBP</DefaultCurrency>
<IRmark>
</IRmark>
<Sender>Employer</Sender>
</IRheader>
</IRenvelope>
</Body>
</GovTalkMessage>
and I'm loading it into a XMLDocument using the XMLDocument.load().
Now when I run xpath queries against it they are not responding as I would expect and I cant seem to find out why, I have used XPath Visualiser tool and it shows that for example //Keys/Key should return 4 nodes
When I run the following c#
document.SelectNodes(#"//Keys/Key") it returns 2 nodes not the expected 4.
Also when I run the following
document.SelectNodes(#"//Header") it returns 0 nodes
Also running
document.SelectNodes(#"GovTalkMessage") returns 0 nodes.
All suggestions and help greatfully received.
Thanks
Ben
XPath needs namespaces. The tags you are trying to select are in one, so you have to tell the select where to look.

Count records using LINQ2XML

I need to get the count of the inbound transactions and the outbound transactions separately. I have tried everything I know, but nothing is working. Here's the XML:
<?xml version="1.0" encoding="utf-8"?>
<records>
<inbound>
<transaction>
<customerID>0002</customerID>
<customerName>bob</customerName>
</transaction>
<transaction>
<customerID>0003</customerID>
<customerName>harry</customerName>
</transaction>
.
.
.
<transaction>
<customerID>0250</customerID>
<customerName>joe</customerName>
</transaction>
</inbound>
<outbound>
<transaction>
<customerID>0002</customerID>
<customerName>bob</customerName>
</transaction>
<transaction>
<customerID>0003</customerID>
<customerName>harry</customerName>
</transaction>
.
.
.
<transaction>
<customerID>0175</customerID>
<customerName>frank</customerName>
</transaction>
</outbound>
</records>
This needs to be in C# and LINQ. Thanks for any help.
Here is how to get the number of transactions for inbounds:
var xdoc = XDocument.Parse(xml);
var c = xdoc.Descendants("inbound").Descendants("transaction").Count();

Categories