Unable to parse XAML/XML - c#

Can you help me in parsing this XAML?
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
EntryPointAssembly="Hello" EntryPointType="Hello.App" RuntimeVersion="4.7.50308.0">
<Deployment.Parts>
<AssemblyPart x:Name="Hello" Source="Hello.dll" />
</Deployment.Parts>
</Deployment>
I have tried XmlDocument, XElement, and XamlReader. None is able to load the XAML and fetch me the values.
Update - Code I tried
var appXaml = ... ; //the XAML string mentioned above
XmlDocument:
var x = new XmlDocument();
x.LoadXml(appXaml);
Also,
//I created XSD from the XAML using xsd.exe
//Placed it in "D:\AppManifest.xsd"
var n = new XmlDocument();
var ss = new XmlSchemaSet();
var s = new XmlSchema() { SourceUri = #"D:\AppManifest.xsd" };
ss.Add(s);
ss.Compile();
n.Schemas.Add(ss);
n.LoadXml(appXaml);
XSD code:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="NewDataSet" targetNamespace="http://schemas.microsoft.com/client/2007/deployment" xmlns:mstns="http://schemas.microsoft.com/client/2007/deployment" xmlns="http://schemas.microsoft.com/client/2007/deployment" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" attributeFormDefault="qualified" elementFormDefault="qualified" xmlns:app1="http://schemas.microsoft.com/winfx/2006/xaml">
<xs:element name="Deployment">
<xs:complexType>
<xs:sequence>
<xs:element name="Deployment.Parts" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="AssemblyPart" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="Name" msdata:Prefix="x" type="xs:string" />
<xs:attribute name="Source" form="unqualified" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="EntryPointAssembly" form="unqualified" type="xs:string" />
<xs:attribute name="EntryPointType" form="unqualified" type="xs:string" />
<xs:attribute name="RuntimeVersion" form="unqualified" type="xs:string" />
</xs:complexType>
</xs:element>
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="Deployment" />
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
XElement:
var z = XElement.Parse(appXaml);
XamlReader:
var l = XamlReader.Parse(appXaml);

try passing xml to parse.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"D:\OldDesktop\Try\app.xaml");
XElement.Parse(xmlDoc.InnerXml);
or iterate through xmldoc
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"D:\OldDesktop\Try\app.xaml");
foreach (XmlElement xElement in xmlDoc.DocumentElement)
{
//do somthing
}

I found that the XAML content that I read from the file contained BOM.
I BOM is stripped out, the XAML code is parsable.
I use Visual Studio 2010. The "Text Visualizer" in debugging mode did not show any sign of BOM (the XAML string is in UTF8). But when I accidently copied the text from the visualizer and pasted in Notepad++, it showed '?' symbol (BOM, in this case.)
Bah. Weird problems in VS.

Related

How to iterate/traverse XML file elements( which contains different namespaces) to convert it as Data table in C#

I have a sample to read a xml schema set for a xml file which contains different namespaces. For this i can get different schema for each namespace as i explained below.
Sample File:
<?xml version="1.0" encoding="utf-8"?>
<data xmlns:d="http://sampleschema/dataservices" xmlns:m="http://sampleschema/dataservices/metadata">
<content>
<m:properties>
<d:CustomerID>ALFKI</d:CustomerID>
<d:CompanyName>Alfreds Futterkiste</d:CompanyName>
</m:properties>
</content>
</data>
Sample Code to get XML Schema Set:
strFileName = #"C:\Sample\Sample.xml";
XmlReader reader = XmlReader.Create(strFileName);
XmlSchemaInference schema = new XmlSchemaInference();
XmlSchemaSet schemaSet = schema.InferSchema(reader);
It gives three different types of schemas while using the above code. But my requirement will be i need a single schema for the entire xml file which contain any number of namespaces in it. I have checked with possibilities of codes in msdn and stack overflow. I can't find any proper solution for this.
The expected schema output will be like below.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="data">
<xs:complexType>
<xs:sequence>
<xs:element name="content">
<xs:complexType>
<xs:sequence>
<xs:element name="m:properties">
<xs:complexType>
<xs:sequence>
<xs:element name="d:CustomerID" type="xs:string"></xs:element>
<xs:element name="d:CompanyName" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="xmlns:d" type="xs:string"></xs:attribute>
<xs:attribute name="xmlns:m" type="xs:string"></xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
Any one can help to achieve this requirement.
Thanks in advance.
Try something like this :
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:m="http://www.w3.org/2001/XMLSchema" xmlns:d="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="data">
<xs:complexType>
<xs:sequence>
<xs:element name="content">
<m:complexType>
<m:sequence>
<m:element name="properties">
<d:complexType>
<d:sequence>
<d:element name="CustomerID" type="xs:string"></d:element>
<d:element name="CompanyName" type="xs:string"></d:element>
</d:sequence>
</d:complexType>
</m:element>
</m:sequence>
</m:complexType>
</xs:element>
</xs:sequence>
<d:attribute name="xmlns_d" type="d:string"></d:attribute>
<m:attribute name="xmlns_m" type="d:string"></m:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

Removing element from XML in C# with an attribute

I m new into C#. I m trying to delete the element having attribute name = "companyKey"
I have tried to do so through the following code:
XElement xml = XElement.Parse(results);
xml.Elements("NewDataSet")
.Attributes("companyKey").Remove();
DataSet ds = new DataSet();
using (var reader = xml.CreateReader())
ds.ReadXml(reader);
However, It is not excluding/deleting the element. Any help/clue would be appreciated.
The XML I m using to apply this code is:
<NewDataSet>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Table1">
<xs:complexType>
<xs:sequence>
<xs:element name="companyKey" type="xs:string" minOccurs="0" />
<xs:element name="phoneVisits" type="xs:int" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
Elements will only return the child elements from the current node, not the children's children (otherwise known as descendants). You then select and remove the attribute, not the element. As that child element and attribute don't exist, you have an empty sequence so nothing is removed.
What you want to do is find all descendant elements where the element contains your name attribute. Try:
XNamespace xs = "http://www.w3.org/2001/XMLSchema"
xml.Descendants(xs + "element")
.Where(x => (string)x.Attribute("name") == "companyKey")
.Remove();

DataSet XML Response from Web Service consumption

Below is the valid and updated XML I was trying to consume:
<DataSet xmlns="http://tempuri.org/">
<xs:schema xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="NewDataSet">
<xs:element name="response">
<xs:complexType>
<xs:sequence>
<xs:element name="user" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="id" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="status" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="code" type="xs:string"/>
<xs:attribute name="value" type="xs:string"/>
<xs:attribute name="description" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="error" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="code" type="xs:string"/>
<xs:attribute name="message" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="operation" type="xs:string"/>
<xs:attribute name="timestamp" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="response"/>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
<NewDataSet xmlns="">
<response diffgr:id="response1" msdata:rowOrder="0" diffgr:hasChanges="inserted" operation="AUTHENTICATION" timestamp="2015-11-19 18:21:17.457" msdata:hiddenresponse_Id="0">
<user diffgr:id="user1" msdata:rowOrder="0" diffgr:hasChanges="inserted" id="blumaesnetwork" msdata:hiddenresponse_Id="0"/>
<status diffgr:id="status1" msdata:rowOrder="0" diffgr:hasChanges="inserted" code="315" value="FAILED" description="Authentication Failed. User ID Not Found" msdata:hiddenresponse_Id="0"/>
<error diffgr:id="error1" msdata:rowOrder="0" diffgr:hasChanges="inserted" code="-1" message="User Not Found" msdata:hiddenresponse_Id="0"/>
</response>
</NewDataSet>
</diffgr:diffgram>
</DataSet>
With the C# code below:
x.LoadXml(_xmlString);
XDocument x1 = new XDocument();
x1 = XDocument.Parse(_xmlString);
IEnumerable<responseStatus> ListRsts = (from e in x1.Descendants("responseStatus")
select new responseStatus
{
code = e.Element("code").Value,
value = e.Element("value").Value,
description = e.Element("description").Value
});
foreach (var br in ListRsts)
codeField = (br.code);
It keeps throwing error that i missed "diffgr".
What you get as a respsone XML is a saved DataSet. Instead of trying to decipher the diffgram it generates you better leverage the ReadXml method of that type. It is fully equipped to read the xml and gives you specified behavior on the Tables and Relationships.
var ds = new DataSet();
ds.ReadXml(File.Open(#"C:\temp\ds.xml", FileMode.Open));
var listOfStatus = from row in ds.Tables["response"].Rows.Cast<DataRow>()
from status in row.GetChildRows("response_status")
select new { code = status["code"],
value = status["value"],
description = status["description"] };
foreach(var stat in listOfStatus)
{
// do what ever you need to do with the Status record(s)
}
In the above code I read the rows in the table response and then fetch the childrows for the table status. For every status row an anonymous type is created with the three fields you seem to be interested in. You can process those by iterating over the IEnumerable of that anonymous type.

C# : Add xs:schema to creating file XML

I have a datatable and I wanna export it to XML file. In my XML file, I want it have schema, as this format :
-<NewDataSet>
-<xs:schema xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="" id="NewDataSet">
-<xs:element msdata:UseCurrentLocale="true" msdata:IsDataSet="true" name="NewDataSet">
-<xs:complexType>
-<xs:choice maxOccurs="unbounded" minOccurs="0">
-<xs:element name="Table1">
-<xs:complexType>
-<xs:sequence>
<xs:element name="MA_NVGCS" minOccurs="0" type="xs:string"/>
<xs:element name="MA_KHANG" minOccurs="0" type="xs:string"/>
<xs:element name="MA_DDO" minOccurs="0" type="xs:string"/>
<xs:element name="MA_DVIQLY" minOccurs="0" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
-<Table1>
<MA_NVGCS/>
<MA_KHANG>PC06LL0192456</MA_KHANG>
<MA_DDO>PC06LL0192456001</MA_DDO>
<MA_DVIQLY>PC06LL</MA_DVIQLY>
</Table1>
I'm using code :
ds.Tables[0].WriteXml(#"C:\Temp\text.xml");
But it just export to format :
-<NewDataSet>
-<Table>
<STATUS>Online</STATUS>
<MESH>false</MESH>
<NGAYGIO>2015-10-05T14:00:27+07:00</NGAYGIO>
<MA_DVIQLY>DSP</MA_DVIQLY>
</Table>
How can I export my XML with xs:schema
Thanks and sorry for my English.
I add XmlWriteMode.WriteSchema to my code ( ds.Tables[0].WriteXml(#"C:\Temp\text.xml", XmlWriteMode.WriteSchema); ) and the problem is solved. Thank to read my stupid question :D

Why does this XML validate, when it shouldn't?

I have the following XSD files:
ReadFile.xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="elsag:lprcore" elementFormDefault="qualified" targetNamespace="elsag:lprcore" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="Read.xsd" />
<xs:element name="reads" type="ReadFile" />
<xs:complexType name="ReadFile">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="read" nillable="true" type="read">
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
Read.xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="elsag:lprcore" elementFormDefault="qualified" targetNamespace="elsag:lprcore" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="Snapshot.xsd"/>
<xs:include schemaLocation="GPS.xsd"/>
<xs:simpleType name="guid">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" />
</xs:restriction>
</xs:simpleType>
<xs:element name="read" type="read"/>
<xs:complexType name="read">
<xs:complexContent mixed="false">
<xs:extension base="snapshot">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="timestamp" type="xs:dateTime" />
<xs:element minOccurs="1" maxOccurs="1" name="plate" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="state" type="xs:string" />
<xs:element minOccurs="1" maxOccurs="1" name="confidence" type="xs:int" />
<xs:element minOccurs="1" maxOccurs="1" name="overviews">
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="snapshot" type="snapshot"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element minOccurs="1" maxOccurs="1" name="gps" type="gps" />
</xs:sequence>
<xs:attribute name="id" type="guid" use="required" />
<xs:attribute name="camera" type="xs:string" use="required" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
Please note that there are more files that make up the XSD, but I don't believe they're relevant to the problem so I did not include them.
I'm using the following code to validate XML files being processed. I want to reject any file that doesn't validate without errors:
StringBuilder validationErrors = new StringBuilder();
inDoc.Validate( schemas, ( o, e ) => {
validationErrors.AppendLine( e.Message );
} );
if ( !string.IsNullOrWhiteSpace( validationErrors.ToString() ) ) {
. . .
}
I've passed the following XML file to the code above and the code does not generate any validation error messages for it.
<read>
<timestamp>2015-07-17T16:20:18.1540000-04:00</timestamp>
<plate>FED456</plate>
</read>
I would have thought that the lack of the reads tag surrounding the read tag would have caused the XML to fail validation. Is the problem in the validation code or is it in the XSD or is this normal?
EDIT:
Here is the code that initializes the schemas variable:
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add( "elsag:lprcore", #"XML\ReadFile.xsd" );
Because you have defined
<xs:element name="read" type="read"/>
the read element is a valid root element for your XML. Every element which is an immediate child of <xs:schema> is eligible for being a root element (even those in an included schema).
Thanks to information posted in the answer by Glorfindel and the link posted by overslacked, I've been able to get the XML validation in my program to work.
The problem was that the program would not flag an XML file that does not contain a namespace as invalid. The cause is that the XDocument.Validate extension method creates an XmlReader object whose XmlReaderSettings property does not contain the ReportValidationWarnings flag. As a result, the ValidationEventHandler delegate passed to the method is not called for these files.
To make the validation logic work, I defined a new extension method that includes the flag:
internal static class XmlValidationExtension {
public static void ValidateWithWarnings( this XDocument doc, XmlSchemaSet schemas, ValidationEventHandler validationCallback ) {
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add( schemas );
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += new ValidationEventHandler( validationCallback );
XmlReader reader = XmlReader.Create( doc.CreateReader(), settings );
while ( reader.Read() ) ;
}
}
This is essentially the same exact code from the question linked to by overslacked, but where the XmlReader is created by calling the XDocment object's CreateReader method.
This code now considers any XML file which does not use the correct namespace to be invalid. Any other part of the XML that does not match the XSD is also flagged.

Categories