How to query this attribute value with Linq to XML - c#

I have a XML document that's in the following format:
<?xml version="1.0" encoding="utf-8"?>
<?mso-infoPathSolution name="urn:schemas-microsoft-com:office:infopath:blah:-myXSD-2007-03-14T00-26-45" solutionVersion="1.0" productVersion="15.0.0.0" PIVersion="1.0.0.0" href="http://blah/FormServerTemplates/blah.xsn"?>
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.4"?>
<my:myFields xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution" xmlns:pc="http://schemas.microsoft.com/office/infopath/2007/PartnerControls" xmlns:ma="http://schemas.microsoft.com/office/2009/metadata/properties/metaAttributes" xmlns:d="http://schemas.microsoft.com/office/infopath/2009/WSSList/dataFields" xmlns:q="http://schemas.microsoft.com/office/infopath/2009/WSSList/queryFields" xmlns:dms="http://schemas.microsoft.com/office/2009/documentManagement/types" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2007-03-14T00:26:45" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xml:lang="en-US">
<my:workDay>MON-FRI</my:workDay>
</my:myFields>
I tried to query the workday with the following code but got null.
var xdoc = XDocument.Load(file);
var workDay = from x in xdoc.Descendants("workDay")
select x.Value;
What did I do wrong?

you need to include the namespace for my::
var xdoc = XDocument.Load(file);
XNamespace myNamespace = "http://schemas.microsoft.com/office/infopath/2003/myXSD/2007-03-14T00:26:45";
var workDay = from x in xdoc.Descendants(myNamespace + "workDay")
select x.Value;

Related

How to merge one specific tag into one XML using c#?

I have two XMLs'
XML1:
'<?xml version="1.0" encoding="utf-8"?>
<Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Filename>1234</Filename>
<Sequence Type="FRONT">
<Object>
<Value>3421</Value>
<Value>John</Value>
</Object>
</Sequence>
</Data>'
XML2:
'<?xml version="1.0" encoding="utf-8"?>
<Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Filename>1234</Filename>
<Sequence Type="FRONT">
<Object>
<Value>1234</Value>
<Value>SAM</Value>
</Object>
</Sequence>
</Data>'
I want the output like below
'<?xml version="1.0" encoding="utf-8"?>
<Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Filename>1234</Filename>
<Sequence Type="FRONT">
<Object>
<Value>3421</Value>
<Value>John</Value>
</Object>
<Object>
<Value>1234</Value>
<Value>SAM</Value>
</Object>
</Sequence>
</Data>'
I.e I want to merge Object tag from XML2 to XML1 using C# code.
Could someone please help me?
You can use XPath to select the nodes you need and then simply use .NET xml using System.Xml
For more information look at https://www.w3schools.com/xml/xpath_intro.asp
Load Xml Documents
I saved the two sample xml-files you provided to separate files and imported them like this
XmlDocument doc1 = new XmlDocument();
XmlDocument doc2 = new XmlDocument();
using (var sw = new StreamReader("xml1.xml"))
{
var text = sw.ReadToEnd();
doc1.LoadXml(text);
}
using (var sw = new StreamReader("xml2.xml"))
{
var text = sw.ReadToEnd();
doc2.LoadXml(text);
}
Select nodes with XPATH
We will take all elements that have the name 'object' and add them to child of the other xml's 'sequence'-element. Therefore we select the 'sequence'-element of one document and the 'object'elements of the other document.
var sequenceNodes = doc1.SelectSingleNode("/Data/Sequence");
var objectNodes = doc2.SelectNodes("/Data/Sequence/Object");
Concat the nodes into one document
Then we take each 'object'-element, import it into the other document-context and append it under the 'sequence'-node
foreach (XmlNode node in objectNodes)
{
XmlNode importedNode = doc1.ImportNode(node, true);
sequenceNodes.AppendChild(importedNode);
}
Output the file
using (var stringWriter = new StringWriter())
using (var xmlTextWriter = XmlWriter.Create(stringWriter))
{
doc1.WriteTo(xmlTextWriter);
xmlTextWriter.Flush();
File.AppendAllText("out.xml", stringWriter.GetStringBuilder().ToString());
}
The outputfile looks like this:
Please, take a look at this solution:
what-is-the-fastest-way-to-combine-two-xml-files-into-one
Using Union method seems to be what you are seeking.
Run an XSLT transformation:
<xsl:template name="merge">
<Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Filename>1234</Filename>
<Sequence Type="FRONT">
<xsl:copy-of select="document('a.xml')//Object"/>
<xsl:copy-of select="document('b.xml')//Object"/>
</Sequence>
</Data>
</xsl:template>
Try following linq which joins all filenames with same value.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication166
{
class Program
{
const string FILENAME1 = #"c:\temp\test.xml";
const string FILENAME2 = #"c:\temp\test1.xml";
static void Main(string[] args)
{
XDocument doc1 = XDocument.Load(FILENAME1);
XNamespace ns1 = doc1.Root.GetDefaultNamespace();
XDocument doc2 = XDocument.Load(FILENAME2);
XNamespace ns2 = doc2.Root.GetDefaultNamespace();
var joins= from d1 in doc1.Descendants(ns1 + "Data")
join d2 in doc2.Descendants(ns2 + "Data")
on (string)d1.Element(ns1 + "Filename") equals (string)d2.Element(ns2 + "Filename")
select new { d1 = d1, d2 = d2};
foreach (var join in joins)
{
XElement d2Object = join.d2.Descendants("Object").FirstOrDefault();
join.d1.Descendants("Sequence").FirstOrDefault().Add(XElement.Parse(d2Object.ToString()));
}
}
}
}

c# get values from xml response

I am trying to get values from xml respone :
<?xml version="1.0" encoding="utf-8"?>
<Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://adaddaasd.com">
<A>14</A>
<B>Failed</B>
<C>22</C>
</Response>
My code is :
string responseString = await response.Content.ReadAsStringAsync();
var xDocument = XDocument.Parse(responseString);
var responseNode = xDocument.XPathSelectElement("/Response");
var A = xDocument.XPathSelectElement("/Response/A");
But I am getting null values for A and responseNode. Whats wrong? Thanks
You're blatantly ignoring the XML namespace that's defined in your XML document:
<Response xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns='http://adaddaasd.com'>
****************************
You need to include that into your querying - I would try to do it like this:
var xDocument = XDocument.Parse(responseString);
// *define* your XML namespace!
XNamespace ns = "http://adaddaasd.com";
// get all the <Response> nodes under the root with that XML namespace
var responseNode = xDocument.Descendants(ns + "Response");
// from the first <Response> node - get the descendant <A> nodes
var A = responseNode.FirstOrDefault()?.Descendants(ns + "A");
If you insist on using the XPathSelectElement method, then you must define an XmlNamespaceManager and use it in your XPath select:
// define your XML namespaces
XmlNamespaceManager xmlnsmgr = new XmlNamespaceManager(new NameTable());
xmlnsmgr.AddNamespace("ns", "http://adaddaasd.com");
// use the defined XML namespace prefix in your XPath select
var A = xDocument.XPathSelectElement("/ns:Response/ns:A", xmlnsmgr);

Can't resolve namespace while parsing a XML wih XDocument

I need some help parsing this XML.
I recieve the following string and I need to obtain the value of "MensajeError".
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<WS_SSPBA_001_SResponse xmlns="http://tempuri.org/">
<WS_SSPBA_001_SResult>
<Estado>boolean</Estado>
<Mensaje>string</Mensaje>
<CodigoError>string</CodigoError>
<MensajeError>error1</MensajeError>
</WS_SSPBA_001_SResult>
</WS_SSPBA_001_SResponse>
</soap:Body>
</soap:Envelope>
I made it to the Body tag but I can't manage to parse further down the XML
var xDocument = XDocument.Parse(resultado);
XNamespace soapenv = "http://schemas.xmlsoap.org/soap/envelope/";
var xElements =
xDocument.Descendants(soapenv + "Body").First()
Anything I tried to parse que tag "" failed. I only need to retrieve the tag "MensajeError"
Thanks!
You could just use the LocalName:
var nodeValue = XDocument.Parse(resultado)
.Descendants()
.First(n => n.Name.LocalName == "MensajeError")
.Value;
//nodeValue = "error1"

why is item is null in xml document?

I have created the following xml file:
<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<channel>
<item>
<g:id>6945</g:id>
<g:price>1222.00</g:price>
</item>
</channel>
</rss>
I need to use the g:id to find the item node because in the real xmlfile I have hundreds of items. However at the moment I am trying to select itemnode but this is null?:
XNamespace g = "http://base.google.com/ns/1.0";
var doc = XDocument.Load(Server.MapPath("~/xmlfile1.xml"));
var reader = doc.CreateReader();
var namespaceManager = new XmlNamespaceManager(reader.NameTable);
namespaceManager.AddNamespace("g", g.NamespaceName);
var itemNode = doc.XPathSelectElement("/Channel/item/g:id[text()= 6945]", namespaceManager);
The XPath you're using is incorrect. Following should work:
var itemNode = doc.XPathSelectElement("//channel/item/g:id[text()= 6945]", namespaceManager);

read xml with linq

I want to read the names form this xml:
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://mysite.com/">
<name>2</name>
<name>3</name>
<name>4</name>
</string>
Tried:
var doc = XElement.Parse(s);
foreach (var v in doc.Descendants("name"))
{
//do work
}
but it does not work. Why?
Because you have a custom namespace - you need to specify the namespace when you select the elements - try this (tested and worked):
XNamespace xmlns = "http://mysite.com/";
var doc = XElement.Parse(s);
foreach (var v in doc.Descendants(xmlns + "name"))
{
//do work
}

Categories