XML to LINQ with metadata - c#

I'm very new to both XML and LINQ. I've read several XML to LINQ tutorials, but none of the XML documents seem to be formatted the way mine is. I'm not sure if (and how) it changes things.
All the examples I've read on the internet seem to follow this format:
<data>
<row>
<Term>201320</Term>
<Subj>ACCT</Subj>
<Subj_desc>Accounting</Subj_desc>
</row>
<row>
<Term>201320</Term>
<Subj>ACCT</Subj>
<Subj_desc>Accounting</Subj_desc>
</row>
</data>
If I wanted to read that I think the code would look something like this:
XDocument document = XDocument.Load("URLHERE.xml");
var term = from row in document.Descendants("row")
select new
{
Term = row.Element("Term").Value,
Subject = row.Element("Subj").Value,
Subject_Description = row.Element("Subj_desc").Value,
};
Here's the problem: my XML document doesn't follow the same format. Instead of repeating the different tags for each term, it has a set of metadata at the top and then uses the SAME tag for each set of data.
Here's a sample of my XML document:
<metadata>
<item name="TERM" type="xs:string" length="128"/>
<item name="SUBJ" type="xs:string" length="128"/>
<item name="SUBJECT_DESC" type="xs:string" length="512"/>
</metadata>
<data>
<row>
<value>201320</value>
<value>ACCT</value>
<value>Accounting</value>
</row>
<row>
<value>201320</value>
<value>ACCT</value>
<value>Accounting</value>
</row>
</data>
How would I extract data from it?
var term = from row in document.Descendants("row")
select new
{
Term = row.Element("value").Value,
Subject = row.Element("value").Value,
};
Doesn't seem right. I'm using C# BTW (not sure if I need to say that or if the tag's sufficient).

Your XML is not properly formatted, you need a root element that encapsulates the entire document. such as
<?xml version='1.0' encoding='utf-8'?>
<root>
<metadata>
<item name="TERM" type="xs:string" length="128"/>
<item name="SUBJ" type="xs:string" length="128"/>
<item name="SUBJECT_DESC" type="xs:string" length="512"/>
</metadata>
<data>
<row>
<value>201320</value>
<value>ACCT</value>
<value>Accounting</value>
</row>
<row>
<value>201320</value>
<value>ACCT</value>
<value>Accounting</value>
</row>
</data>
</root>
Then using XDocument you could load the file
var doc = XDocument.Load("file.xml");
then you can extract the data, kinda depends what you want to extract, you never specified. example of getting the metadata
var item = doc.Descendants("metadata");
getting rows, containing an IEnumerable of values
XDocument document = XDocument.Load("c:\\tmp\\test.xml");
var rows = from i in document.Descendants("row")
select new {values = i.Elements("value").Select(a=>a.Value)};

Related

How to return a list of serializable XML elements

I know how to make function return a "pretty" result as xml, and I want just that, but without the extra parent element.
Using this function
[HttpGet]
public XElement MyFunction() { ... }
gets me half way. I get this:
<Result>
<row>
<cell>...</cell>
<cell>...</cell>
<cell>...</cell>
</row>
<row>
<cell>...</cell>
<cell>...</cell>
<cell>...</cell>
</row>
</Result>
I want result like this:
<row>
<cell>...</cell>
<cell>...</cell>
<cell>...</cell>
</row>
<row>
<cell>...</cell>
<cell>...</cell>
<cell>...</cell>
</row>
And using function like this:
[HttpGet]
public IEnumerable<XElement> MyFunction() { ... }
Gets me a result like this:
<ArrayOfXElement
xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/System.Xml.Linq">
<XElement>
<row xmlns="">
<cell>...</cell>
<cell>...</cell>
<cell>...</cell>
</row>
</XElement>
<XElement>
<row xmlns="">
<cell>...</cell>
<cell>...</cell>
<cell>...</cell>
</row>
</XElement>
etc...
Which is, I mean... look at it... its hideous.
I beleave that there must be a simple solution to this, or at least a workaround.
EDIT As #Fabio suggested in the first comment, XML is invalid if it has no root element, and thus, this question becomes silly, since I do need other systems to be able to read the result of my functions. Even so, I will not remove this question, because I hope that somebody else who needs a solution like this will, like me, realise that that kind of XML document is invalid. Also, if anyone answers the question, I will approve the answer.
get a reader and get the innerXml. This should get you what you need.
var MainElement= XElementA.CreateReader();
MainElement.MoveToContent();
var Content=MainElement.ReadInnerXml();

Return XML response with metadata from asp .net core Web API

How can I return an XML response from webAPI written in .net core to have the metadata information at the top.
Required response :
<?xml version="1.0" encoding="UTF-8"?>
<dataset xmlns="http://developer.cognos.com/schemas/xmldata/1/"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
<metadata>
<item name="AsOfDate" type="xs:string" length="12"/>
<item name="RateOfReturn" type="xs:double"/>
<item name="FamAcctIndex" type="xs:string" length="3"/>
<item name="RowID" type="xs:string" length="1"/>
<item name="BrM" type="xs:string" length="1"/>
<item name="ProductLineCode" type="xs:int"/>
</metadata>
<data>
<row>
<value>Apr 26, 2002</value>
<value>0.210066429</value>
<value>JA1</value>
<value>F</value>
<value>B</value>
<value>1</value>
</row>
<row>
<value>Apr 27, 2002</value>
<value>0.1111111</value>
<value>BBB</value>
<value>G</value>
<value>B</value>
<value>2</value>
</row>
</data>
</dataset>
I have added the following code to accept xml type :
services.AddMvc().AddXmlSerializerFormatters();
My API method returns XML without the metadata if I use Accept : application/xml

Reading and Editing XML file

I have an XML file which contains employee details. How can i edit the existing employee names in that MXL file using C# .NET.
Here is the xml file.
<?xml version="1.0" encoding="utf-8"?>
<Employees>
<Employee id="1">
<Name>Employee 1</Name>
<Designation>SE </Designation>
<Qualification>MCA </Qualification>
</Employee>
<Employee id="2">
<Name>Employee 2</Name>
<Designation>SE </Designation>
<Qualification>MCA </Qualification>
</Employee>
<Employee id="3">
<Name>Employee 3</Name>
<Designation>SE </Designation>
<Qualification>MCA </Qualification>
</Employee>
</Employees>
How can i edit the employee names. I am new to xml. For example using Console Application
You can simple do that using Linq to Xml.
using System.Xml.Linq;
...
XDocument xDoc = XDocument.Load(#"Your xml file path goes here"); // or XDocument.Parse("Your xml string goes here");
xDoc.Root.Elements("Employee").First(xe => xe.Attribute("id").Value == "1").Element("Name").Value = "your value";
Here is a good reference for head start: Programming Guide (LINQ to XML)
you can use XML Serialization, in my opinion this is the most comfortable way
of working with c# and xml,
some examples are here:
http://msdn.microsoft.com/en-us/library/58a18dwa(v=vs.110).aspx

How parse XML with metadata in C#?

I have a problem with parsing above XML code. It doesn't look like normal XML structure - in the top of document is schema, which describe fields. Is there any simple method for parsing it?
<metadata>
<item name="number" type="xs:string" length="42"/>
<item name="artist" type="xs:string" length="62"/>
<item name="title" type="xs:string" length="502"/>
<item name="title supplement" type="xs:string" length="502"/>
<item name="price" type="xs:decimal" scale="2" precision="12"/>
</metadata>
<data>
<row>
<value>88697562032</value>
<value>1979 Revival Cast Recording</value>
<value>Oklahoma!</value>
<value>Softpack</value>
<value>25</value>
</row>
(...)
<row>
<value>88697919802</value>
<value>2CELLOS (Sulic & Hauser)</value>
<value>2CELLOS</value>
<value>Three Language Booklet Version</value>
<value>39.6</value>
</row>
</data>

Deserialize with XmlSerializer having external xmlns reference

I have an ever increasing number of BCP (t-sql) format files in XML that I need to read. I create the xsd file using xsd.exe and a number of BCP format files and attempt to read the xml file as an object. But it fails like this:
Unhandled Exception: System.InvalidOperationException: There is an error in XMLdocument (4, 6). ---> System.InvalidOperationException: The specified type was not recognized: name='CharTerm', namespace='http://schemas.microsoft.com/sqlserver/2004/bulkload/format', at .
The XML file is like this:
<?xml version="1.0" encoding="utf-8" ?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RECORD>
<FIELD ID="1" xsi:type="CharTerm" TERMINATOR=";" MAX_LENGTH="32"/>
<FIELD ID="2" xsi:type="CharTerm" TERMINATOR=";" MAX_LENGTH="4"/>
<FIELD ID="3" xsi:type="CharTerm" TERMINATOR=";" MAX_LENGTH="4"/>
<FIELD ID="4" xsi:type="CharTerm" TERMINATOR=";" MAX_LENGTH="20"/>
<FIELD ID="5" xsi:type="CharTerm" TERMINATOR="\r\n" MAX_LENGTH="16"/>
</RECORD>
<ROW>
<COLUMN SOURCE="1" NAME="col1" xsi:type="SQLNVARCHAR"/>
<COLUMN SOURCE="2" NAME="col2" xsi:type="SQLINT"/>
<COLUMN SOURCE="3" NAME="col3" xsi:type="SQLINT"/>
<COLUMN SOURCE="4" NAME="col4" xsi:type="SQLNVARCHAR"/>
<COLUMN SOURCE="5" NAME="col5" xsi:type="SQLFLT4"/>
</ROW>
</BCPFORMAT>
I read the XML file like this:
FileStream fs = File.OpenRead(formatFileName);
XmlSerializer serializer = new XmlSerializer(typeof(FormatSchemasXml.BCPFORMAT));
FormatSchemasXml.BCPFORMAT bcp_format = (FormatSchemasXml.BCPFORMAT)serializer.Deserialize(fs);
fs.Close();
The external xmlns reference does not seem to be used. I have searched a lot of documentation, but failed at seeing how I can fix this. Preferably without having to modify the BCP XML format files (I'd like to use them as is).
Suggestions?

Categories

Resources