Select XML node without have the namespace included - c#

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?

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));

Removing Attribute value based on value from an XML using VB.Net

I have an XML as below
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope
xmlns="http://com/uhg/uht/uhtSoapMsg_V1"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header>
<uhtHeader
xmlns="http://com/uhg/uht/uhtHeader_V1">
<consumer>COMET</consumer>
<auditId></auditId>
<sendTimestamp>2020-09-03T18:15:40.942-05:00</sendTimestamp>
<environment>P</environment>
<businessService version="24">getClaimHistory</businessService>
<status>success</status>
</uhtHeader>
</env:Header>
<env:Body>
<srvcRspn
xmlns="http://com/uhg/uht/getClaimHistory_V24">
<srvcErrList arrayType="srvcErrOccur[1]" type="Array">
<srvcErrOccur>
<orig>Foundation</orig>
<rtnCd>00</rtnCd>
<explCd>000</explCd>
<desc></desc>
</srvcErrOccur>
</SrvcErrList>
</srvcRspn>
</env:Body>
</env:Envelope>
I want to remove all the attribute values with "http" like below:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope
xmlns=""
xmlns:env="">
<env:Header>
<uhtHeader
xmlns="">
<consumer>COMET</consumer>
<auditId></auditId>
<sendTimestamp>2020-09-03T18:15:40.942-05:00</sendTimestamp>
<environment>P</environment>
<businessService version="24">getClaimHistory</businessService>
<status>success</status>
</uhtHeader>
</env:Header>
<env:Body>
<srvcRspn
xmlns="">
<srvcErrList arrayType="srvcErrOccur[1]" type="Array">
<srvcErrOccur>
<orig>Foundation</orig>
<rtnCd>00</rtnCd>
<explCd>000</explCd>
<desc></desc>
</srvcErrOccur>
</SrvcErrList>
</srvcRspn>
</env:Body>
</env:Envelope>
I have tried several ways but none of them has worked for me. Can anyone suggest what is fastest way to do it in VB.NET/C#.
The actual response is very large (approx 100000 lines of XML minimum) and using for each will consume a good amount of time. Is there any parsing method or LINQ query method which can do it faster.
I got the way to do it using Regex as below:
Return Regex.Replace(xmlDoc, "((?<=<|<\/)|(?<= ))[A-Za-z0-9]+:| xmlns(:[A-Za-z0-9]+)?="".*?""", "")
It serves my purpose completely. Thanks Cleptus for your quick reference.

Reading data from XML using C#

I have to read the ordertext ("This is an example text") from this XML File:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<order id="">
<users>
<user id="123456" nick="nick" done="false" />
</users>
<machines>
<machine id="1234" sd="1234" ref="" done="false" />
</machines>
<todos />
<ordertexts>
<ordertext>This is an example text </ordertext>
</ordertexts>
</order>
My C# Code looks like this:
XmlDocument xDoc = new XmlDocument();
xDoc.Load(file);
XmlElement node = (XmlElement)xDoc.SelectSingleNode("/order/ordertexts/ordertext");
When I write the selected data in another XML File it looks like this:
<order>
<oldOrderText>System.Xml.XmlElement</oldOrderText>
</order>
What did I do wrong? Is the XPath incorrect?
I am a C# newbie so I really need every help I can get!
Thanks in advance, geibi
What you're looking for is XmlElement.InnerText.
When you get the node using this:
XmlElement node = (XmlElement)xDoc.SelectSingleNode("/order/ordertexts/ordertext");
You still need to use this:
string neededText = node.InnerText;
to get the value of that node.
Suppose that you're writing the results in a console application. If you try to write the node variable, this way:
Console.WriteLine(node);
Since node is not a string, and it's an XmlElement object, the ToString method of XmlElement is going to be called, which returns the object name, hence your new XML had the result as System.Xml.XmlElement and not the desired text.

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.

WCF/SOAP: Move XML namespace definition to parent element

I use WCF to implement a client for a SOAP web service. The code is generated by "Add Service Reference" based on the WSDL file.
The elements of the SOAP request are defined in different namespaces.
Now, a sample message looks like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<myMethod xmlns="http://example.org/xsd/requests">
<RequestData>
<Foo xmlns="http://example.org/xsd/elements">some</Foo>
<Bar xmlns="http://example.org/xsd/elements">thing</Bar>
<Baz xmlns="http://example.org/xsd/elements">content</Baz>
<!-- .... more elements .... -->
</RequestData>
</myMethod>
</s:Body>
</s:Envelope>
which contains the redundant definition of the elements namespace. In order to reduce message size, I would prefer to have the namespace definitions at the top of the message, eg. like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:a="http://example.org/xsd/requests"
xmlns:b="http://example.org/xsd/elements">
<a:myMethod>
<a:RequestData>
<b:Foo>some</b:Foo>
<b:Bar>thing</b:Bar>
<b:Baz>content</b:Baz>
<!-- .... more elements .... -->
</a:RequestData>
</a:myMethod>
</s:Body>
</s:Envelope>
(I don't really care which parent element defines the namespaces, so any way to move the namespace definitions to Envelope, Body or MyMethod would be okay for me.)
How can I achieve this?
EDIT: removed local xmlns definitions in second example (copy-paste mistake ;) )

Categories