Unable to use xpath as expected on document - c#

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.

Related

Converting graphml to image

I have this script that creates a .graphml file, and it looks great in yEd (Link to software), but I'm trying to automate the extra step of having this file, opening it in a different program, doing some edits in there etc etc.
I was wondering if there was some way to automate this into a png image, preferably a hexagonal grid or Vornoi in C#, depending on whether or not each node is connected to exactly 6 or not.
The .graphml file structure looks as follows:
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="d2" for="node" attr.name="value" attr.type="long" />
<key id="d1" for="node" attr.name="y" attr.type="long" />
<key id="d0" for="node" attr.name="x" attr.type="long" />
<graph edgedefault="directed">
<node id="(0, 1)">
<data key="d0">0</data>
<data key="d1">1</data>
<data key="d2">0</data>
</node>
.
.
.
<node id="(39, 38)">
<data key="d0">39</data>
<data key="d1">38</data>
<data key="d2">4</data>
</node>
<edge source="(0, 1)" target="(1, 1)"></edge>
<edge source="(0, 1)" target="(0, 2)"></edge>
.
.
.
<edge source="(39, 38)" target="(38, 39)"></edge>
</graph>
</graphml>
The value is a direct one-to-one mapping of the node's colour.
And the coordinates are in the following pattern if it were a regular hexagonal grid:
Hope this query makes sense!
Kind regards.

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.

Select XML node without have the namespace included

I have some XML that has a namespace..
<batch xmlns="http://www.mydomain.uk/batch" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="applications.xsd">
<header>
...
</header>
<applications>
<application>
<details>
<Title>MR</Title>
<Forename>Jonathh</Forename>
<Middlenames>
<Middlename>on</Middlename>
<Middlename>ath</Middlename>
</Middlenames>
<PresentSurname>H</PresentSurname>
</details>
</application>
</applications>
</batch>
I am need to pull out the applications.. which I am able to do - but only by specifying the namespace..
var namespaceManager = new XmlNamespaceManager(doc.NameTable);
namespaceManager.AddNamespace("eb", "http://www.mydomain.uk/batch");
var protectedElement = doc.SelectSingleNode("/eb:batch/eb:applications", namespaceManager);
The problem for me is that the namespace then propagates down to the selected node E.G.
<applications xmlns="http://www.mydomain.uk/batch">
<application>
<details>
<Title>MR</Title>
<Forename>Jonathh</Forename>
<Middlenames>
<Middlename>on</Middlename>
<Middlename>ath</Middlename>
</Middlenames>
<PresentSurname>H</PresentSurname>
</details>
</application>
</applications>
Note the sneaky little xmlns in the applications tag now.. that wasn't there before.. I've tried all sorts of things to remove..
I am so desperate I am considering a regular expression instead (I know!) - which I actually don't think would be too awful here....
Anyone got any suggestions?

Passing XML multi level data as parameter and using in stored procedure

I have XML format data which I will pass from a .net application.
In the SQL Server stored procedure, this data is passed in as a XML parameter. I want to read and save the data in the required tables, say TblOrder and TblItem.
In XML, there will be multiple orders. Each order contains one or several items accordingly.
Structure on which operation need to be implemented:
<?xml version="1.0" encoding="UTF-8"?>
<Orders>
<Order>
<B2>B2**ABIJ**0000884443**PP</B2>
<CreateBy null="true" />
<CreateDate>/Date(1485150414358)/</CreateDate>
<CurrencyId>1</CurrencyId>
<CustomerId>13</CustomerId>
<DeliveryAddress>LIBERTY PRESS LLC</DeliveryAddress>
<DeliveryCity>SPRINGVILLE UT 84663</DeliveryCity>
<DeliveryCityId>0</DeliveryCityId>
<DeliveryDate>/Date(1478750400000)/</DeliveryDate>
<DeliveryId>14</DeliveryId>
<DeliveryState>UT</DeliveryState>
<DeliveryStateId>16</DeliveryStateId>
<DeliveryType>Delivery</DeliveryType>
<EquipmentId>4</EquipmentId>
<Items>
<Item>
<CSA>false</CSA>
<CTPAT>false</CTPAT>
<CommodityItem>General Freight</CommodityItem>
<CommodityItemId>0</CommodityItemId>
<CustCommodityItem null="true" />
<FAST>false</FAST>
<Hazmat>false</Hazmat>
<Height null="true" />
<IsActive>false</IsActive>
<ItemId>0</ItemId>
<ItemName>Item A</ItemName>
<Length null="true" />
<Make null="true" />
<Mass null="true" />
<MassUnit null="true" />
<Model null="true" />
<OrderId>0</OrderId>
<PIP>false</PIP>
<PilotCar>false</PilotCar>
<ReeferTemp null="true" />
<Tarp>false</Tarp>
<TrailerType null="true" />
<TruckType null="true" />
<VIN null="true" />
<Width null="true" />
<Year null="true" />
</Item>
</Items>
<L11>L11*SYL884443*BM</L11>
<LastUpdate>/Date(1485150414358)/</LastUpdate>
</Order>
<Order>
...
<Items>
<Item>
...
</Item>
</Order>
</Orders>
Steps I want to achieve are:
Read XML parameter from the stored procedure, which is passed from the .net application.
Loop through the XML and save data in the TblOrder and TblItem tables
Going through the article follows :
Pass-XML-parameter-to-Stored-Procedure
How to loop and parse xml parameter in sql server stored procedure
I got the Idea to access very first level (in my case Order of Orders).
Moving forward having issue accessing the second level which will be again a collection (in my case Item of Items of Order).
Thanks in advance for your support
You have two approaches:
You can pass the XML as-is into a Stored Procedure and do all the hard work in T-SQL
You can shredd the XML within C#, fill appropriate data objects and use classical data storage.
From your question I take, that you'd prefer to pass this into a stored procedure as XML parameter. There are some things to know:
C# uses 16-bit-unicode internally and so does SQL Server's XML. But you will not be able to cast this unicode string to XML as long as there is encoding="UTF-8" included... You might pass this as VARCHAR(MAX) (not NVARCHAR(MAX)!), but this could lead you in troubles if there are sepcial characters involved. Best was, to cut the first line (the <?xml ...?> declaration) away completely.
Your XML is not created correctly. Is this under you control? If you include null="true" (there's no need for normally!), you should do this with the xsi-namespace. And date/time values within XML should be ISO8601. Your values (like /Date(1485150414358)/) are no format SQL Server will be able to cast directly...
Nevertheless I see multi <Order>-elements and multi <Item>-elements. You could read them as follows:
DECLARE #xml XML=
N'<Orders>
<Order>
<B2>B2**ABIJ**0000884443**PP</B2>
<CreateBy null="true" />
<CreateDate>/Date(1485150414358)/</CreateDate>
<CurrencyId>1</CurrencyId>
<CustomerId>13</CustomerId>
<DeliveryAddress>LIBERTY PRESS LLC</DeliveryAddress>
<DeliveryCity>SPRINGVILLE UT 84663</DeliveryCity>
<DeliveryCityId>0</DeliveryCityId>
<DeliveryDate>/Date(1478750400000)/</DeliveryDate>
<DeliveryId>14</DeliveryId>
<DeliveryState>UT</DeliveryState>
<DeliveryStateId>16</DeliveryStateId>
<DeliveryType>Delivery</DeliveryType>
<EquipmentId>4</EquipmentId>
<Items>
<Item>
<CSA>false</CSA>
<CTPAT>false</CTPAT>
<CommodityItem>General Freight</CommodityItem>
<CommodityItemId>0</CommodityItemId>
<CustCommodityItem null="true" />
<FAST>false</FAST>
<Hazmat>false</Hazmat>
<Height null="true" />
<IsActive>false</IsActive>
<ItemId>0</ItemId>
<ItemName>Item A</ItemName>
<Length null="true" />
<Make null="true" />
<Mass null="true" />
<MassUnit null="true" />
<Model null="true" />
<OrderId>0</OrderId>
<PIP>false</PIP>
<PilotCar>false</PilotCar>
<ReeferTemp null="true" />
<Tarp>false</Tarp>
<TrailerType null="true" />
<TruckType null="true" />
<VIN null="true" />
<Width null="true" />
<Year null="true" />
</Item>
</Items>
<L11>L11*SYL884443*BM</L11>
<LastUpdate>/Date(1485150414358)/</LastUpdate>
</Order>
</Orders>';
--the query
SELECT --elements of Order
o.value(N'(B2)[1]',N'nvarchar(max)') AS B2
--very strange date-format...
,o.value(N'(CreateDate)[1]',N'nvarchar(max)') AS CreateDate
--typed INT
,o.value(N'(CurrencyId)[1]',N'int') AS CurrencyId
--more like this
--elements of Item
,i.value(N'(CSA)[1]',N'nvarchar(max)') AS CSA
--There's no need for *null="true"*
--Query the "/text()" and the empty element will be NULL
,CASE WHEN i.value(N'(CustCommodityItem/#null)[1]',N'nvarchar(max)')=N'true' THEN NULL ELSE i.value(N'(CustCommodityItem)[1]',N'nvarchar(max)') END AS CustCommodityItem_complicated
,i.value(N'(CustCommodityItem)[1]',N'nvarchar(max)') AS CustCommodityItem_empty
,i.value(N'(CustCommodityItem/text())[1]',N'nvarchar(max)') AS CustCommodityItem_null
FROM #xml.nodes(N'/Orders/Order') AS A(o)
OUTER APPLY o.nodes(N'Items/Item') AS B(i)

Xdocument throws error while XMLdocument loads sucessfully the same xml string

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

Categories