I need to read configuration elements from the web.config.
Let this be my web.config.
<family>
<parents>
<child name="Hello"/>
<child name="World"/>
</parents>
<parents>
<child name="Hello1"/>
<child name="World2"/>
</parents>
</family>
So I have something like this, I need to read this into a collection.
How can i do this????
In general, you can store simple application settings and connection string in web.config (or app.config), but anything more complex, like an object graph or XML (as in your case) and you should consider a different method.
These may be helpful:
How do I store an XML value in my .NET App.Config file
(it suggests encoding the XML in an app setting)
However it would be better to have a separate XML data file and convert it to an object graph using Linq-To-XML (see reference) or XPath and the XmlDocument and related classes.
Edit: see the other answer, which does allow XML in the config file. That's a more direct answer to your exact questions but I will leave this here for reference. On the whole it looks like your data is not configuration data (more like runtime / user data) and does not belong in a .config file: so I would recommend storing it in a separate XML file, and having a config file entry pointing to the filename of the separate XML file.
Hope that helps!
You need to define your own custom configuration section, which will allow you to read the nested configuration element properly. BTW, this is the same method that all the others use, for instance the Enterprise Library components, NHibernate, etc.
The steps you need to take are very straightforward, and a tutorial is provided here:
http://msdn.microsoft.com/en-us/library/2tw134k3.aspx
You need to use the ConfigurationElementCollection Class.
See this sample on the MSDN
public struct Child
{
public string name;
public Child(string name)
{
this.name = name;
}
}
public class Parent
{
public List<Child> childs = new List<Child>();
public static List<Parent> ReadParentsFromXml(string fileName)
{
List<Parent> parents = new List<Parent>();
System.Xml.XmlTextReader doc = new System.Xml.XmlTextReader(fileName);
Parent element = new Parent();
while (doc.Read())
{
switch (doc.Name)
{
case "parents":
if (doc.NodeType == System.Xml.XmlNodeType.EndElement)
{
parents.Add(element);
element = new Parent();
}
break;
case "child":
if(doc.NodeType != System.Xml.XmlNodeType.EndElement)
element.childs.Add(new Child(doc.GetAttribute(0)));
break;
}
}
return parents;
}
}
Related
I need to read some XML files that follow the ONIX standard
See: http://www.editeur.org/93/Release-3.0-Downloads/
To do this i downloaded the ONIX 3.0 XSD:
http://www.editeur.org/files/ONIX%203/ONIX_BookProduct_XSD_schema+codes_Issue_25.zip
Using the downloaded XSD and this command "xsd your.xsd /classes" i created classes that i want to use.
When trying to create a new Xml Serializer like so:
var xmls = new XmlSerializer(typeof(Model.ONIX.editeur.ONIXMessage));
I get and exception
"There was an error reflecting type 'Model.ONIX.editeur.ONIXMessage'."
When i drill down through the inner exceptions i end up with this message:
"{"Member 'Text' cannot be encoded using the XmlText attribute. You
may use the XmlText attribute to encode primitives, enumerations,
arrays of strings, or arrays of XmlNode."}"
I am not sure what to do, is something wrong with the XSD? Any suggestions?!
Edit
public static List<Model.ONIX.editeur.Product> GetProductsDataFromOnixFile(string onixFileLocation)
{
var xmls = new XmlSerializer(typeof(Model.ONIX.editeur.ONIXMessageRefname));
using (var reader = XmlReader.Create(onixFileLocation))
{
if (xmls.CanDeserialize(reader))
{
var onixMessage = (Model.ONIX.editeur.ONIXMessage)xmls.Deserialize(reader);
return onixMessage.Items.OfType<Model.ONIX.editeur.Product>().ToList();
}
throw new Exception(string.Format("Cant read the file {0} as Onix", onixFileLocation));
}
}
I know this question is old but I assume others with specific Onix issues will run into this.
Here is how I got it to work.
In the reference xsd are two includes in the top. Here I copy/pasted the other two files in.
<xs:include schemaLocation="ONIX_BookProduct_CodeLists.xsd" />
<xs:include schemaLocation="ONIX_XHTML_Subset.xsd" />
I.e. these lines are replaced in the file with the corresponding file.
Then I did the
xsd ONIX_BookProduct_3.0_reference.xsd /classes
And then it generates the .cs file. And the only issue I had here was I had to remove a text attribute from all fields that was e.g. List147, but not from the fields that was string. E.g. I had to remove the attribute from generated code like this:
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public List121 textscript {
get {
return this.textscriptField;
but not from attributes like this
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public string Value {
get {
return this.valueField;
I have a C# Web Service that is serializing my simple class:
[Serializable]
[XmlInclude(typeof(Bitmap))]
[XmlTypeAttribute(Namespace = "http://tempuri.org/")]
public class Class1
{
private static Bitmap _myImage = new Bitmap(#"C:\WebApplication1\ClassLibrary1\Untitled.png");
public Bitmap MyImage
{
get { return _myImage; }
set
{
_myImage = value;
}
}
}
Here's the asmx.cs code that does the serialization:
[WebMethod]
public string HelloWorld()
{
var c = new Class1();
XmlSerializer serializer = new XmlSerializer(typeof(Class1));
return XMLSerializer(c);
}
public string XMLSerializer(object pObject)
{
try
{
XmlSerializer xs = new XmlSerializer(pObject.GetType());
using (StringWriter stream = new StringWriter())
{
xs.Serialize(stream, pObject);
stream.Flush();
return stream.ToString();
}
}
catch (Exception ex)
{
return ex.ToString();
}
}
Looks prety straight forward. However, the XML generated by the XmlSerializer is producing and error when I try to DeSerialize it.
{"There is an error in XML document (5, 5)."}
{"Parameter is not valid."}
When I try to load the generated XML into IE I get this error.
Switch from current encoding to specified encoding not supported. Error processing resource 'file:///C:/Users/mhall15/Deskt...
<?xml version="1.0" encoding="utf-16"?>
Here's the generated XML:
<?xml version="1.0" encoding="utf-16"?>
<Class1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MyImage xmlns="http://tempuri.org/">
<Palette />
</MyImage>
</Class1>
Any ideas what's going on?
During the serialization, replace "encoding="utf-16" with "encoding="utf-8"" and that will cut it. The source of the problem - I'm not sure, but I've ran into it numerous times, and that's how I dealt with it.
That's how to deal with the IE issue.
The deserialization should be amongst these lines. I'm posting the kind of arbitrary code I normally use:
public static object DeserializeFromXML<T>(string _input)
{
object _temp = Activator.CreateInstance<T>();
Type expected_type = _temp.GetType();
_temp = null;
XmlSerializer serializer = new XmlSerializer(expected_type);
StringReader stringWriter = new StringReader(_input);
object _copy = serializer.Deserialize(stringWriter);
return _copy;
}
In the above example, I'm using templating for reusability sake. You should be able to call the method by saying DeserializeFromXML < Class1 >(_xml_input) where xml input is the string. That will force the compiler to use the definition of the given class to deserialize the XML input. That way you wouldn't even have to change the encoding in the serialization. If it's also a case where you may or may not know the data type to deserialize with, you can use a strategy design pattern where you register the root type of the XML with it's associated generic type. Later on you can reference that registry and arbitrarily deserialize any XML input as long as the root type is registered. It's a trick i normally use as well. If more is needed on this, let me know, and I'll explain in detail.
In addition,if you are running IE 9, the new update to IE 9 makes it difficult to view XML. Press F12 - go to developer tools and change your browser mode to run as IE 8 instead of IE 9.
I was using a certain method for parsing my app.config file. Then I was told that using ConfigurationManager is better and simpler. But the thing is I don't know how to do it with ConfigurationManager.
My original code looked like this:
XmlNode xmlProvidersNode;
XmlNodeList xmlProvidersList;
XmlNodeList xmlTaskFactoriesList;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("app.config");
xmlProvidersNode = xmlDoc.DocumentElement.SelectSingleNode("TaskProviders");
xmlProvidersList = xmlProvidersNode.SelectNodes("TaskProvider");
foreach (XmlNode xmlProviderElement in xmlProvidersList)
{
if (xmlProviderElement.Attributes.GetNamedItem("Name").Value.Equals(_taskProvider))
{
xmlTaskFactoriesList = xmlProviderElement.SelectNodes("TaskTypeFactory");
foreach (XmlNode xmlTaskFactoryElement in xmlTaskFactoriesList)
{
if (xmlTaskFactoryElement.Attributes.GetNamedItem("TaskType").Value.Equals(_taskType))
{
taskTypeFactory = xmlTaskFactoryElement.Attributes.GetNamedItem("Class").Value;
}
}
}
}
What would be the equivalent using ConfigurationManager? (Because all I can see is how to get keys not nodes..)
Thanks
Create a class that inherits ConfigurationSection called, say, MyConfigSection. Then you can use the ConfigurationManager.GetSection method to get an instance of your MyConfigSection class. The ConfigurationManager will do all the parsing, so you will have a strongly typed object to work with. Here is an excellent example to follow.
If you are concerned about the custom sections create your own class using Configuration section class. Here is an example about using it.
Okay this one DID it! Thanks to all of you!
public class Result
{
public String htmlEscaped
{
set;
get;
}
[XmlIgnore]
public String htmlValue
{ set; get; }
[XmlElement("htmlValue")]
public XmlCDataSection htmlValueCData
{
get
{
XmlDocument _dummyDoc = new XmlDocument();
return _dummyDoc.CreateCDataSection(htmlValue);
}
set { htmlValue = (value != null) ? value.Data : null; }
}
}
Result r = new Result();
r.htmlValue = ("<b>Hello</b>");
r.htmlEscaped = ("<b>Hello</b>");
XmlSerializer xml = new XmlSerializer(r.GetType());
TextWriter file = new StreamWriter(Environment.CurrentDirectory + "\\results\\result.xml", false, System.Text.Encoding.Default);
xml.Serialize(file, r);
file.Close();
RESULT:
<?xml version="1.0" encoding="Windows-1252"?>
<Result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<htmlEscaped><b>Hello</b></htmlEscaped>
<htmlValue><![CDATA[<b>Hello</b>]]></htmlValue>
</Result>
As you can see, after CDATA is return type, no more escaped html in XML file on filesystem.
The JSON Serialization isn't working anymore, but this can be fixed with a little type extention.
QUESTION WAS:
Maybe someone knows how to make do it...
I have this Class:
public class Result
{
public String htmlValue
{
get;
set;
}
}
I use this to serialize it to XML
Result res = new Result();
res.htmlValue = "<p>Hello World</p>";
XmlSerializer s = new XmlSerializer(res.GetType());
TextWriter w = new StreamWriter(Environment.CurrentDirectory + "\\result.xml", false, System.Text.Encoding.Default);
s.Serialize(w, res);
w.Close();
Works fine i get this:
<?xml version="1.0" encoding="Windows-1252"?>
<Result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<htmlValue><b>Hello World</b></htmlValue>
</Result>
What can do i have to change to get this:
<?xml version="1.0" encoding="Windows-1252"?>
<Result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<htmlValue><![CDATA[<b>Hello World</b>]]></htmlValue>
</Result>
I've already searched but I can't find anything. The type of htmlValue
have to stay String, because of other Serialisations JSON, etc.
Tricky one... Thanks in advance for suggestions
HTML is correct in String within C#. Why decode or encode?
XmlSerializer saved the HTML escaped to XML file.
Don't use C# for consuming.
Is external tool which accept this:
<htmlValue><![CDATA[<b>Hello World</b>]]></htmlValue>
but not
<htmlValue><b>Hello World</b></htmlValue>
I do the same with JSON Serializer, in file on hard drive the HTML is saved correct.
Why and where to use HTTP Utility to prevent that? And how to get <![CDATA[ ]]> around it.
Can you give a code sample?
Are there any other Serializer than the C# own one?
I've found this Link .NET XML Serialization of CDATA ATTRIBUTE from Marco André Silva, which does I need to do, but it's different, how to include this without changing Types?
Here's a simple trick to do achieve what you want. You just need to serialize a XmlCDataSection property instead of the string property :
(it's almost the same as John's suggestion, but a bit simpler...)
public class Result
{
[XmlIgnore]
public String htmlValue
{
get;
set;
}
private static XmlDocument _dummyDoc;
[XmlElement("htmlValue")]
public XmlCDataSection htmlValueCData
{
get { return _dummyDoc.CreateCDataSection(htmlValue); }
set { htmlValue = (value != null) ? value.Data : null; }
}
}
See "CDATA serialization with XMLSerializer" for the same problem, and for the solution.
BTW, it seems to me that if the vendor no longer exists, it's time to use a different product. Possibly one that understands the XML specifications which have only existed for over a decade.
It is my understanding that you need the XML to feed it to some utility. Do you also plan to use it to de-serialize the object?
If not then why do not do it yourself - serialize your object that is? Roundtrip object -> XML -> object is somewhat tricky, but the first part is not.
I'm trying to serialize a custom class that needs to use multiple elements of the same name.
I've tried using xmlarray, but it wraps them in another elements.
I want my xml to look like this.
<root>
<trees>some text</trees>
<trees>some more text</trees>
</root>
My code:
[Serializable(), XmlRoot("root")]
public class test
{
[XmlArray("trees")]
public ArrayList MyProp1 = new ArrayList();
public test()
{
MyProp1.Add("some text");
MyProp1.Add("some more text");
}
}
Try just using [XmlElement("trees")]:
[Serializable(), XmlRoot("root")]
public class test
{
[XmlElement("trees")]
public List<string> MyProp1 = new List<string>();
public test()
{
MyProp1.Add("some text");
MyProp1.Add("some more text");
}
}
Note I changed ArrayList to List<string> to clean up the output; in 1.1, StringCollection would be another option, although that has different case-sensitivity rules.
(edit: obsoleted - my second post ([XmlElement]) is the way to go - I'm leaving this for posterity in using xsd.exe)
xsd.exe is your friend. Copy the xml you want into a file (foo.xml), then use:
xsd foo.xml
xsd foo.xsd /classes
Now read foo.cs; you can use this either directly, or just for inspiration.
(edit: output snipped - not helpful any more)