How parse XML with metadata in C#? - 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>

Related

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

How to do Schematron validation over different xml files attributes

I have one source1.xml file
<?xml version="1.0" encoding="utf-8" ?>
<list>
<author id="a1">Alice</author>
<author id="p1">Paul</author>
<author id="p2">Peter</author>
</list>
another source2.xml
<?xml version="1.0" encoding="utf-8" ?>
<list>
<author id="1"/>
<author id="a2"/>
<author id="p1"/>
</list>
I need to validate "id" attribute of the two xml files are having same values or not.
I can do it using the schematron as shown in this link ( http://zvon.org/xxl/SchematronTutorial/Examples/Example17/example.html)
So I have created on xsd file (source2.xsd) where my schematron is included as shown below
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="list">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="author">
<xs:annotation>
<xs:appinfo>
<sch:pattern name ="Compare AdaptiveDisplayDevice Id with DisplayDevice Id" xmlns:sch="http://www.ascc.net/xml/schematron">
<rule context="author">
<report test="document('source1.xml')//author[#id=current()/#id]">
Atrribute
<name path="document('source1.xml')//author[#id=current()/#id]"/> is forbidden in element
<name/>
</report>
</rule>
</sch:pattern>
</xs:appinfo>
</xs:annotation>
<xs:complexType>
<xs:attribute name="id" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
My C# code to validation is as shown below
using System.Text;
using NMatrix.Schematron;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
/* setup schematron validation */
Validator validator = new Validator();
validator.AddSchema(#"D:\POC\ConsoleApplication1\ConsoleApplication1\source2.xsd");
/* run both validators at once */
validator.Validate(new XmlTextReader(#"D:\POC\ConsoleApplication1\ConsoleApplication1\source2.xml"));
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
}
If we observe two xml files , then while validation using schematron it should give me error at first two id values. However I am not getting any error ..
Can anyone help me here ....

Validating XML against XSD with <xs:any/> - Warning : Could not find schema information for the element

I am trying to validate my XML files against an XSD to check if the files have the correct format.
In my XSd file I want the Row element to contain as many and whatever element possible, thus the any element.
With an online validator, I checked that the validity of XSD and checked my Schema on one of the files I want to check. Everything was valid.
The online validator is this one: http://www.utilities-online.info/xsdvalidation/
I based my parsing code on this topic : c# XML Schema validation
I get that my files are not valid: Could not find schema information for the element <MYELEMENT>
The elements that are not found are the ones in my in the content of my Row element.
The complete .XSD is :
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element name="Row" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:any minOccurs='1' maxOccurs='unbounded' processContents="lax" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
The XML I tested with is :
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Root>
<Row>
<MODE_SAISIE_CT>'DEGRADE'</MODE_SAISIE_CT>
<MODE_STATUT>'F'</MODE_STATUT>
<MODE_LIBELLE>'Dégradé'</MODE_LIBELLE>
<DATE_MODE_DEGRADE>'17/08/2011 15:28:17'</DATE_MODE_DEGRADE>
</Row>
<Row>
<MODE_SAISIE_CT>'STANDARD'</MODE_SAISIE_CT>
<MODE_STATUT>'V'</MODE_STATUT>
<MODE_LIBELLE>'Standard'</MODE_LIBELLE>
<DATE_MODE_DEGRADE>'17/08/2011 15:53:06'</DATE_MODE_DEGRADE>
</Row>
</Root>
How can I manage the parsing if I have an any element in my schema ?
Without seeing a complete XSD and input XML that exhibit the issue, it's unclear what to recommend, but perhaps this working example will help you identify your problem:
This input XML:
<?xml version="1.0" encoding="utf-8"?>
<root>
<Row>
<MYELEMENT/>
</Row>
</root>
Is valid against this XSD:
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Row">
<xsd:complexType>
<xsd:sequence>
<xsd:any processContents="lax" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

XML to LINQ with metadata

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

Do i have to use namespace to match xml documents?

Having a bit of trouble trying to get an xsd to match two documents:
XML Document 1:
<?xml version="1.0" encoding="UTF-8"?>
<video contenttype="asf" fileextension=".wmv" hascontent="no" lang="en-GB" length="1800" pid="3678738364972" sid="">
<lastmodified timestamp="1282678200000">
Tue, 24 Aug 2010 19:30:00 +0000
</lastmodified>
<links/>
<keywords/>
<slides/>
<copyright>
Copyright owned by original broadcaster
</copyright>
<title>
Friends
</title>
<comment>
The One Where the Monkey Gets Away: Rachel accidentally lets Ross's pet monkey escape, then learns that her former best friend is engaged to marry her ex-fiancé. [AD,S]
</comment>
<author>
E4
</author>
<email/>
<captioning/>
<extendeddata>
<data name="keepOriginal">
0
</data>
<data name="keepTranscoded">
0
</data>
<data name="realStartTime">
1282677909
</data>
<data name="scheduledStartTime">
1282678200
</data>
<data name="broadcastLength">
1800
</data>
<data name="broadcastChannel">
E4
</data>
<data name="paddingUsed">
300000
</data>
<data name="transcodingSpec">
-b 2.35M -a 128k --debug --primary-format mp4 --podcast "-l 270 -b 600 -R 48 -B 64" --keep-files true
</data>
<data name="transcoding">
succeeded
</data>
<data name="transcodingProfile">
-b 2.35M -a 128k --debug --primary-format mp4 --podcast "-l 270 -b 600 -R 48 -B 64" --keep-files true
</data>
<data name="transcoderDetails">
ver 1.58.2.1, 2010-08-24 21:31:33 up 5 days, 11:24, 0 users, load average: 3.08, 3.38, 2.67, OS20031 212.70.69.26
</data>
<data name="originalFilename">
/var/lib/etvd/mpegts/E4/Friends (24-Aug-2010 20.30).emcast
</data>
<data name="originalRecordingTime">
created 2010-08-24 , last modified 2010-08-24 : recording lasted 0s
</data>
<data name="primaryFormat">
mp4
</data>
<data name="doXml">
True
</data>
<data name="doFiles">
True
</data>
</extendeddata>
<categories>
<category name="em:podcast">
mp4
</category>
</categories>
</video>
XML Document 2:
<?xml version="1.0" encoding="UTF-8"?>
<video xmlns="UploadXSD">
<title>
A vid with Pete
</title>
<description>
Petes vid
</description>
<contributor>
Pete
</contributor>
<subject>
Cat 2
</subject>
</video>
Proposed XSD:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="UploadXSD"
targetNamespace="UploadXSD"
elementFormDefault="qualified"
xmlns="http://tempuri.org/UploadXSD.xsd"
xmlns:mstns="http://tempuri.org/UploadXSD.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="video">
<xs:complexType>
<xs:sequence>
<xs:element name="title" minOccurs="1" type="xs:string"></xs:element>
<xs:element name="description" type="xs:string"></xs:element>
<xs:element name="contributor" type="xs:string"></xs:element>
<xs:element name="subject" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Is it possible to use c# to validate against both of the xml documents and NOT use a namespace? Because with the XML Document 1 (above) it is created by a third party system and it cannot generate the namespace...
Asked a few questions about xml in the last few days appreciate help am very new to this...
I believe you do need to match namespace. I once faced a similar issue, where the XML document was out of my control (Adobe Smart Forms), and I wanted to validate it against my XSD.
To do this I cleaned the XML document before I validated, adjusting the namespace, and in my case removing alot of garbage that Adobe added. Sorry I don't have any code with me on how I did it.
As far as I'm aware, you don't need a namespace. I've never used one in any of my XSD schemas.
Here's Microsoft's documentation on the feature:
http://msdn.microsoft.com/en-us/library/aa258639%28SQL.80%29.aspx

Categories

Resources