How can i parse this XML with C# WP7 to different lists for binding different panorama pages:
<root>
<main1>
<item>
<id>1</id>
</item>
<item>
<id>2</id>
</item>
</main1>
<main2>
<item>
<id>1</id>
</item>
<item>
<id>2</id>
</item>
<main2>
</root>
The most efficient (and memory preserving) way to parse large XML documents is to use the XmlReader. Se the MSDN howto for a reasonable example.
The easiest way to parse an XML document is usually the XDocument class, but that class reads the whole document into memory at once and is not recommendable for large documents.
Related
I'm making a game, in C# (MonoGame if it makes a difference), and the game has both a server and a client.
I want the client to hold some kind of textual representation of the items, so that when I load the client it will read the file and parse it into game objects so that I can easily handle items.
I thought about using XML or JSON, I know the basics of both, but I really don't know
How to use them in code.
What do you think would be more appropriate? I think XML is more appropriate but I might be wrong, this is why I'm asking...
The file would have this kind of structure
<items>
<item>
<id></id>
<name></name>
<cost></cost>
<description></description>
<pathofimage></pathofimage>
</item>
<item>
<id></id>
<name></name>
<cost></cost>
<description></description>
<pathofimage></pathofimage>
</item>
</items>
How, given this example structure, do I get the data from the file?
It depends, XML is easier to work with using builtin .NET namespaces like System.Xml or System.Xml.Linq.
JSON could be better if you'll use this data in javascript or in some public game API, but it will need some third-party library to work with it like JSON.NET (it gives better json support). Also json is more lightweight then xml and large amount of data will be smaller in json.
parsing code example using linq for xml (System.Xml.Linq namespace):
var xmlString = #"<items>
<item>
<id>100</id>
<name>lance</name>
<cost>9.99</cost>
<description></description>
<pathofimage></pathofimage>
</item>
<item>
<id>101</id>
<name>sword</name>
<cost>12.50</cost>
<description></description>
<pathofimage></pathofimage>
</item>
</items>";
var doc = XDocument.Parse(xmlString);
var items = doc.Root.Elements("item").Select(e => new {
Id = int.Parse(e.Element("id").Value),
Name = e.Element("name").Value,
Cost = decimal.Parse(e.Element("cost").Value)});
results:
(I'm using LinqPad for represent results here, highly recommend it for playing with linq and linq for xml)
I am using an xsl stylesheet to output an xsl:fo document with an SVG chart embedded.
I am having trouble taking an array from the input, and splitting it into several smaller arrays, stored in variables so that the SVG template can be applied to the different arrays to generate 3 different charts. The input looks like this (please note the custom ns):
<root xmlns="http://xml.mynamespace.com">
<data>
<list>
<item>
<id>1</id>
<title>Foo</title>
<score>10</score>
</item>
<item>
<id>2</id>
<title>Bar</title>
<score>6</score>
</item>
<item>
<id>3</id>
<title>Baz</title>
<score>16</score>
</item>
<item>
<id>4</id>
<title>Fizz</title>
<score>14</score>
</item>
<item>
<id>5</id>
<title>Buzz</title>
<score>7</score>
</item>
</list>
</data>
</root>
These value can be split into 3 distinct groups. I am trying to split the array list into 3 separate variables to that a template can be applied to turn them into an SVG chart. The SVG transform is known to work for the array as above, so I think the problem is the way I am trying to create the variables. I have tried a few different ways, but I have had the most success (if you can call it that) using xsl:copy-of as so (again, please be aware of the ns):
<xslt:stylesheet xmlns:m="http://xml.mynamespace.com" version="1.0">
<xsl:variable name="group1">
<xsl:element name="m:list">
<xsl:copy-of select="/m:root/m:data/m:list/m:item[id <= 3]"/>
</xsl:element>
</xsl:variable>
</xslt:stylesheet>
and then later the variable is used like so:
<xsl:apply-templates select="msxsl:node-set($group1)/m:list" />
The reason I am putting them in variables is because the template that creates the SVG expects input in the format of <list> with one or more child item elements. The SVG transform template is as so:
<xsl:template match="m:list">
<xsl:variable name="canvasHeight" select="28 * count(m:item)"/>
<svg height="{$canvasHeight}">
<xsl:for-each select="m:item">
<!-- Draw bar here -->
</xsl:for-each>
</svg>
</xsl:template>
The output when I try to transform the variable to SVG as above indicates that the list element is created correctly (because the template matches and the SVG element is output) but the item elements aren't copied because the for-each doesn't seem to have executed and the outputted height is 0.
Am I incorrectly creating the variable group1? Or is there an easier way to do this that doesn't require splitting the initial list into separate variables?
Well with /m:root/m:data/m:list/m:item[Id <= 3] you simply have the wrong case (Id versus id) and the wrong namespace (none versus m:id) in the predicate.
In DB I have XML strings stored in a column. Below is my XML structure:
<?xml version="1.0"?>
-<ProductAttributes xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-<Attribute Required="false" ID="2" Name="Color">
<Value ID="18">Light Pink</Value>
</Attribute>
-<Attribute Required="false" ID="1" Name="Size">
<Value ID="9">XL</Value>
</Attribute>
</ProductAttributes>
Another XML is:
<?xml version="1.0"?>
-<ProductAttributes xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-<Attribute Required="false" ID="1" Name="Size">
<Value ID="1">S</Value>
</Attribute>
-<Attribute Required="false" ID="2" Name="Color">
<Value ID="4">Red</Value>
</Attribute>
-<Attribute Required="false" ID="3" Name="Weight">
<Value ID="6">10gr</Value>
</Attribute>
</ProductAttributes>
Notes
There can be n number of xml strings and each xml string can have m number of tags
Attribute nodes can in different order, for example in 1st attribute Id=1 can be first attribute and in 2nd attribute Id=1 can be last.
Requirement is not compare these n XML strings and find if any of strings has complete duplication of attributes (this comparison will consider values as order can be different).
Please guide and help me.
don't compare strings of XML. Use them as input to an XML parser that will turn them into XML trees, then search the trees for matching elements and compare their list of attributes.
You could iterate all nodes of xml doc A and for each node, look up its xpath in xml doc B. If any paths are not found or the path is found but the value is different, the doc's are not 'the same'.
You'd then have to do the same for all nodes in B, checking the xpaths in A, to ensure there's nothing "in B but not in A"
Optimise by quitting as 'not equal' as soon as an xpath is not found or the values don't match.
You may want to try The XML Diff and Patch GUI Tool which you can download from here. I've used it before and it works ok.
What is the best way in C# to get a collection of objects representing the changes between two XML texts, e.g.:
First:
<Customer>
<Id>1</Id>
<FirstName>Angie</FirstName>
<LastName>Jones</LastName>
<ZipCode>23434</ZipCode>
<Contracts>
<Contract>
<Id>234</Id>
<Title>Test Contract 1</Title>
</Contract>
</Contracts>
</Customer>
Second:
<Customer>
<Id>1</Id>
<FirstName>Angie</FirstName>
<MiddleName>S.</MiddleName>
<LastName>Jones-Smith</LastName>
<Contracts>
<Contract>
<Id>234</Id>
<Title>Test Contract 1</Title>
</Contract>
<Contract>
<Id>534</Id>
<Title>Test Contract 2</Title>
</Contract>
</Contracts>
</Customer>
Changes:
Kind: Node: Before After
-------- ---------- -------- ----------------
Change Customer/LastName Jones Jones-Smith
Addition Customer/MiddleName S.
Deletion Customer/ZipCode
Addition Customer/Contracts[1] <Contract>
<Id>534</Id>
<Title>Test Contract 2</Title>
</Contract>
The point is to then pass the changes as a collection of objects onto a GUI which can appropriately display them.
What is the best way to go about this, i.e. structure the class(es) that represents the changes and traverse/examine the XML in order to identify the changes most accurately?
This appears to be a duplicate question for: Xml Comparison in C#
Have a look there, see if it helps.
Quote:
I've got an answer by Martin Honnen in
XML and the .NET Framework MSDN Forum.
In short he suggests to use XQuery
1.0's deep-equal function and supplies some C# implementations. Seems to
work.
For this kind of work I have used XMLDiff patch provided by MSFT. It produces a diffgram which you can then represent as a class if you want.
LINQ to XML has a DeepEquals method that I believe you can utilize in this case.
Then perhaps you can use the XSLT/XQuery processor called SAXON to get the differences.
Duplicate: This is a duplicate of Best practices to parse xml files with C#? and many others (see https://stackoverflow.com/search?q=c%23+parse+xml). Please close it and do not answer.
How do you parse XML document from bottom up in C#?
For Example :
<Employee>
<Name> Test </name>
<ID> 123 </ID>
<Employee>
<Company>
<Name>ABC</company>
<Email>test#ABC.com</Email>
</company>
Like these there are many nodes..I need to start parsing from bottom up like..first parse <company> and then and so on..How doi go about this in C# ?
Try this:
XmlDocument doc = new XmlDocument();
doc.Load(#"C:\Path\To\Xml\File.xml");
Or alternatively if you have the XML in a string use the LoadXml method.
Once you have it loaded, you can use SelectNodes and SelectSingleNode to query specific values, for example:
XmlNode node = doc.SelectSingleNode("//Company/Email/text()");
// node.Value contains "test#ABC.com"
Finally, note that your XML is invalid as it doesn't contain a single root node. It must be something like this:
<Data>
<Employee>
<Name>Test</Name>
<ID>123</ID>
</Employee>
<Company>
<Name>ABC</Name>
<Email>test#ABC.com</Email>
</Company>
</Data>