I’m after some C# code that will have the following methods that will return Xml as the result.
Search the Apple iTunes App store. If I pass it a name or partial name the function must return a list of possible search results or just one result if it is a perfect match.
Example shown below:
<App>
<AppId>321564880</AppId>
<Name>Doodle Clock - Clock A Doodle Do!</Name>
<ReleaseDate>Released Sep 28, 2009</ReleaseDate>
<Artist>YARG</Artist>
<Description>Description of App</Description>
<Copyright>© YARG Limited 2009</Copyright>
<Price>$0.99</Price>
<Category>Lifestyle</Category>
<MainImageUrl><!—main App icon image urlà </ImageUrl>
<ExtraImages>
<!-- these will be the extra images you see in the App store other than the main application icon -->
<ImageUrl> <!—url of extra image 1à</ImageUrl>
<ImageUrl> <!—url of extra image 2à</ImageUrl>
<ImageUrl> <!—url of extra image 3à</ImageUrl>
</ExtraImages>
<Version>Version: 1.1 (iPhone OS 3.0 Tested)</Version>
<Size>1.5 MB</Size>
</App>
Okay the best way to create xml file and parse and manipulate them is using XDocument,XElement,etc. Because they are enumerable which means you can use LINQ on them and that will help you a lot.
For example :
XElement element = new XElement("Persons",
new XElement("Person","John",
new XAttribute("Id","1")),
new XElement("Person","Aaron",
new XAttribute("Id",2))
)
returns
<Persons>
<Person Id="1">John</Person>
<Person Id="2">Aaron</Person>
</Person>
More information : System.Xml.Linq Namespace
If you are looking for speed, then you can use XMLReader and XMLWriter but you can't find the flexibility that System.Xml.Linq provides.
You should use XPath in .NET:
http://www.aspfree.com/c/a/.NET/Working-with-XPath-The-NET-Way/
I would use XmlTextReader. It's the fastest way (though read-forward-only) - if you are maybe looking for speed. If not, XPath should do.
Related
Simplified XML file I need to decode:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:deliverylistResponse xmlns:ns2="http://tdriverap3.wsbeans.iseries/">
<return>
<COUNT>3</COUNT>
<DELIVERIES>
<ADD1>1300 address 1</ADD1>
<CITY>NICE CITY</CITY>
<ZIP>85705</ZIP>
</DELIVERIES>
<DELIVERIES>
<ADD1>40 S PINAL PKWY AVE</ADD1>
<CITY>FLORENCE</CITY>
<ZIP>85132</ZIP>
</DELIVERIES>
<DELIVERIES>
<ADD1>1825 EAST MAIN</ADD1>
<CITY>CHANDLER</CITY>
<ZIP>85286</ZIP>
</DELIVERIES>
<ERRORCODE/>
<RUNDATE>09/26/2018</RUNDATE>
</return>
</ns2:deliverylistResponse>
</soap:Body>
</soap:Envelope>
I am using the following to try and decode each of the individual addresses in the code.
I cannot figure out how to access them.
XElement xelement = XElement.Load(#"e:\test\X2.xml");
IEnumerable<XElement> addresses = xelement.Elements();
foreach (var address in addresses)
{
Console.WriteLine(address);
Console.WriteLine(address.Element("CITY").Value);
}
The first writeline works (it outputs the entire XML tree), the second says "System.Xml.Linq.XContainer.Element(...) returned null" - I have tried using DELIVERIES, COUNT, Body etc...
Obviously I am not telling it correctly how to traverse the structure, but I do not know how to go any further with it..
UPDATE: Thanks to some help I have figured out how to do it using Linq.
I would still like to be able to deserialize it if anybody has a pointer.
I followed several tutorials, but the multiple levels of this XML seems to be throwing me off.
I have created a class to hold the data but that is as far as my success with that path has gone.
Thank you,
Joe
Thank you Crowcoder -- this is what I wound up with, which will work.
The real XML file however does have about 60 fields so this is not as good as using a deserialize routine but I can at least move forward with the project.
XElement xelement = XElement.Load(#"e:\test\x2.xml");
IEnumerable<XElement> textSegs =
from seg in xelement.Descendants("DELIVERIES")
select seg;
foreach (var address in textSegs)
{
Console.WriteLine(address.Element("ADD1").Value);
Console.WriteLine(address.Element("CITY").Value);
Console.WriteLine(address.Element("ZIP").Value);
}
Console.ReadKey();
I am tasked with ripping and stripping pertinent data from XFDL files. I am attempting to use XmlDocument's SelectSignleNode method to do so. However, it has proven unsuccessful.
Represntative XML:
<XFDL>
...
<page1>
<check3>true</check3>
</page1>
...
<page sid="PAGE1">
<check sid="CHECK9">
<value>true</value>
</check>
</page>
...
Code:
XmlDocument document = new XmlDocument();
document.Load(memoryStream);//decoded and unzipped xfdl file
//Doesn't work
XmlNode checkBox = document.SelectSingleNode("//check[#sid='CHECK9']/value");
//Doesn't work
XmlNode checkBox = document.SelectSingleNode("//page[#sid='PAGE1']/check[#sid='CHECK9']");
MsgBox(checkBox.InnerXml);
Yields me System.NullReferenceException as an XmlNode isn't selected.
I think I'm having an xpath issue but I can't seem to understand where. The earlier xml node is easily selected using:
XmlNode checkBox = document.SelectSingleNode("//page1/check3");
MsgBox(checkBox.InnerText);
Displays just fine. And just to head it off at the pass, there isn't a definition of <check9></check9> in the <page1> tag.
Anyone have some insight?
Thanks in advance.
Okay, so here's the deal. XFDL defines a default namespace that requires an arbitrary mapping for xpath querying. In my case:
XML:
<XFDL xmlns="http://www.ibm.com/xmlns/prod/xfdl/8.0" ... >
Code:
manager.AddNamespace("a", "http://www.ibm.com/xmlns/prod/xfdl/8.0");
//Append 'a:' to query elements
document.SelectSingleNode("//a:check[#sid='CHECK9']/a:value", manager);
The problem is compounded because <check> is buried in <page> which is defined in another namespace: xfdl. My xpath query becomes:
document.SelectSingleNode("//xfdl:page[#sid='PAGE1']/a:check[#sid='CHECK9']/a:value", manager);
Now this is rather XFDL specific but can be applied to other issues where there are multiple namespaces defined within an XML document.
EDIT 1
Source: http://codeclimber.net.nz/archive/2008/01/09/How-to-query-a-XPath-doc-that-has-a-default.aspx
I'm trying to do very simple operations on a .cxml file. As you know it's basically an .xml file. This is a sample file I created to test the application:
<?xml version="1.0" encoding="utf-8"?>
<Collection xmlns:p="http://schemas.microsoft.com/livelabs/pivot/collection/2009" SchemaVersion="1.0" Name="Actresses" xmlns="http://schemas.microsoft.com/collection/metadata/2009">
<FacetCategories>
<FacetCategory Name="Nationality" Type="LongString" p:IsFilterVisible="true" p:IsWordWheelVisible="true" p:IsMetaDataVisible="true" />
</FacetCategories>
<!-- Other entries-->
<Items ImgBase="Actresses_files\go144bwo.0ao.xml" HrefBase="http://www.imdb.com/name/">
<Item Id="2" Img="#2" Name="Anna Karina" Href="nm0439344/">
<Description> She is a nice girl</Description>
<Facets>
<Facet Name="Nationality">
<LongString Value="Danish" />
</Facet>
</Facets>
</Item>
</Items>
<!-- Other entries-->
</Collection>
I can't get any functioning simple code like:
XDocument document = XDocument.Parse(e.Result);
foreach (XElement x in document.Descendants("Item"))
{
...
}
The test on a generic xml is working. The cxml file is correctly loaded in document.
While watching the expression:
document.Descendants("Item"), results
the answer is:
Empty "Enumeration yielded no results" string
Any hint on what can be the error? I've also add a quick look to get Descendants of Facet, Facets, etc., but there are no results in the enumeration. This obviously doesn't happen with a generic xml file I used for testing. It's a problem I have with .cxml.
Basically your XML defines a default namespace with the xmlns="http://schemas.microsoft.com/collection/metadata/2009" attribute:
That means you need to fully qualify your Descendants query e.g.:
XDocument document = XDocument.Parse(e.Result);
foreach (XElement x in document.Descendants("{http://schemas.microsoft.com/collection/metadata/2009}Item"))
{
...
}
If you remove the default namespace from the XML your code actually works as-is, but that is not the aim of the exercise.
See Metadata.CXML project under http://github.com/Zoomicon/Metadata.CXML sourcecode for LINQ-based parsing of CXML files.
Also see ClipFlair.Metadata project at http://github.com/Zoomicon/ClipFlair.Metadata for parsing one's CXML custom facets too
BTW, at http://ClipFlair.codeplex.com can checkout the ClipFlair.Gallery project for how to author ASP.net web-based forms to edit metadata fragments (parts of CXML files) and merge them together in a single one (that you then convert periodically to DeepZoom CXML with PAuthor tool from http://pauthor.codeplex.com).
If anyone is interested in doing nesting (hierarchy) of CXML collections see
http://github.com/Zoomicon/Trafilm.Metadata
and
http://github.com/Zoomicon/Trafilm.Gallery
I am using WorkflowMarkupSerializer to save a statemachine workflow - it saves the states OK, but does not keep their positions. The code to write the workflow is here:
using (XmlWriter xmlWriter = XmlWriter.Create(fileName))
{
WorkflowMarkupSerializer markupSerializer
= new WorkflowMarkupSerializer();
markupSerializer.Serialize(xmlWriter, workflow);
}
The code to read the workflow is:
DesignerSerializationManager dsm
= new DesignerSerializationManager();
using (dsm.CreateSession())
{
using (XmlReader xmlReader
= XmlReader.Create(fileName))
{
//deserialize the workflow from the XmlReader
WorkflowMarkupSerializer markupSerializer
= new WorkflowMarkupSerializer();
workflow = markupSerializer.Deserialize(
dsm, xmlReader) as Activity;
if (dsm.Errors.Count > 0)
{
WorkflowMarkupSerializationException error
= dsm.Errors[0]
as WorkflowMarkupSerializationException;
throw error;
}
}
}
Open Control Panel -> "Regional and language options" and set list separator to ',' (comma)
and workflow serializer will use ',' (comma) as separator for X,Y coordinates for struct SizeF
then select ';' and workflow serializer will use ';' (semicolon) as separator.
This really stupid that serializer use regional setting for serialize markup.
The position of all the states is kept in a separate file. You'll need to drag it around with the markup of the workflow itself. Luckily, it's just XML as well, so you might be able to reuse most of the code you have up there. If memory serves, I believe it's simply NameOfYourWorkflow.layout.
I agree with x0n - the designer is really bad in Visual Studio.
OK, this tutorial gives good information on how to do it - although so far I am only able to save the layout, I haven't been able to correctly use the layout. The information in question is about 2/3rds down (or just do a search for .layout)
(How does one close his own question?)
Note that there is a bug in either the serialize or deserialize of the XML created (named in the example with an extension of .layout.)
It produces the following xml as the first line of the file:
<?xml version="1.0" encoding="utf-8"?><StateMachineWorkflowDesigner xmlns:ns0="clr-namespace:System.Drawing;Assembly=System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" Name="New" Location="30, 30" Size="519, 587" AutoSizeMargin="16, 24" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
When reading this back in, the size attribute causes an exception. I removed Size="519, 587" from the file and the workflow is loaded back correctly. Right now, I write the file, open it and remove the size, then close it. I need to think about a more elegant solution, but at least I am now saving and restoring a state machine workflow.
Hah, even the workflow designer hosted in Visual Studio 2008 loses the positions of states randomly. This tells me it's probably not an easy task, and is information external to the Activities that comprise it. I'd dig more around the host for information; if I find something, I'll post back.
I have a set of configuration items I need to persist to a "human readable" file. These items are in a hierarchy:
Device 1
Name
Channel 1
Name
Size
...
Channel N
Name
...
Device M
Name
Channel 1
Each of these item could be stored in a Dictionary with a string Key and a value. They could also be in a structure/DTO.
I don't care about the format of the file as long as it's human readable. It could be XML or it could have something more like INI format
[Header]
Key=value
Key2=value
...
Is there a way to minimize the amount of boiler plate code I would need to write to manage storing/reading configuration items?
Should I just create Data Transfer Objects (DTO)/structures and mark them serializable (Does that generate bloated XML still human readable?)
Is there other suggestions?
Edit: Not that the software has to write as well as read the config. That leaves app.config out.
YAML for .NET
I think both the XmlSerializer and NetDataContractSerializer create human readable XML. I prefer the NetDataContractSerializer because it can do things the XmlSerializer cannot, but those extra features are probably more than you need for this. If you already have classes written for your configurations, one of these two are probably your shortest path to victory.
You could also write your configurations to the local app.config file, or a sub-config file using custom ConfigSections and the Configuration class.
If you serialize your structure to JSON you get a simpler representation of your object than in XML.
Here's a sample from James Netwon-King's JSON.Net site:
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string json = JavaScriptConvert.SerializeObject(product);
//{
// "Name": "Apple",
// "Expiry": new Date(1230422400000),
// "Price": 3.99,
// "Sizes": [
// "Small",
// "Medium",
// "Large"
// ]
//}
Product deserializedProduct = JavaScriptConvert.DeserializeObject<Product>(json);
You can read his blog and download JSON.Net here.
See the FileHelpers library. It's got tons of stuff for reading from and writing to a lot of different formats - and all you have to do is mark up your objects with attributes and call Save(). Sort of like ORM for flat files.
I suspect that what you'll want to use is an app.config file which contains your settings in an XML format that .NET will be able to load in using the System.Configuration namesapce.
More info here: Link
I've generally used the registry for storing configurations (I know, bad me!), but using System.Xml to read/write a lightweight XML file isn't hard. In fact, I've done just that recently for a plugin project that uses XML documents to communicate with its host as well as store its own persistent settings.
There is also the System.Configuration namespace, but I've not really dealt with it.
I'd use a data structure that can be serialized into XML - in fact, since I'm lazy, I'd use an ADO.NET DataSet, since it has a simple serialization format that you can produce without having to think terribly hard.
As far as making it human-readable goes: if it just has to be human-readable (and not human-modifiable, which I think is what you're describing here), I'd build an XSLT transform and use it to produce an HTML version of the configuration data whenever I wrote out the XML. That gives you as fine-grained control over the visual presentation of the data as you could possibly ask for.
My preference in this situation is to create a DataSet with DataTables for the configuration data arranged in a nice relational way - then use DataSet.WriteXML() to save it to a configuration file.
Then to load it again, you just use DataSet.ReadXML() and it's back in a nice query-able object.
This is an example config file that my app allows the user to edit in a Text Editor window:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!--****************************************************************
Config File: FileToExcel_test.cfg
Author: Ron Savage
Date: 06/20/2008
Description:
File to test parsing a file into an Excel workbook.
Modification History:
Date Init Comment
06/20/2008 RS Created.
******************************************************************-->
<!--********************************************************************
Global Key Definitions
********************************************************************-->
<config key="sqlTimeout" value="1800"/>
<config key="emailSMTPServer" value="smtp-server.austin.rr.com"/>
<config key="LogFile" value="FiletoExcel_test_{yyyy}{mm}{hh}.log"/>
<config key="MaxEntries" value="1"/>
<!--********************************************************************
Delimiter Configurations
********************************************************************-->
<config key="pipe" value="|"/>
<!--********************************************************************
Source / Target Entries
********************************************************************-->
<config key="source_1" value="FILE, c:\inetpub\ftproot\filetoexcel.txt, pipe, , , , , "/>
<config key="target_1" value="XLS, REPLACE, c:\inetpub\ftproot\filetoexcel1.xls, , , , , , , ,c:\inetpub\ftproot\filetoexcel_template.xls, ,3"/>
<config key="notify_1" value="store_error, store_success"/>
</configuration>
When I load it into the DataSet, all the non-comment tags reside in a table named Config with fields Key & value. Very easy to search.