Click here to Skip to main content
15,904,416 members
Please Sign up or sign in to vote.
3.00/5 (2 votes)
See more:
Hi,
I wanted to know is there any way by which i can convert an XML file into an equivalent class file. I have used XSD.EXE tool provided in VS2008, but it is not meeting my requirements. If i use XSD.EXE, I need to do manual changes to that auto generated class file, since every element in XML file has equivalent collection, created in the auto generated class. This will not be flexible. So can anyone help me out. If there is no other go then do i have to code this conversion process?.

Any information will be appreciated. Thanks in advance.
Posted
Comments
Yvan Rodrigues 24-May-11 8:01am    
What is the nature of the class that you want to convert? Is it a business object? Are you just wanting to convert elements to properties, or is there some sort of business logic that needs to be converted too?
SaiprasadVernekar 24-May-11 8:52am    
Thanks for your reply Yvan. I don't have any business logic here. Its just element to class conversion. Please look at the sample xml content of the XML file.
XML file :

<command006 name="Write Polling Address">
<Input>
<PollingAddress DataType="U8" index="0" value="20" />
<loopcurrentmode datatype="U8" index="1" value="10">
</Input>

<responsecode datatype="U8" index="0" value="0">
<statusbyte datatype="U8" index="1" value="50">
<PollingAddress DataType="U8" index="0" value="19" />
<loopcurrentmode datatype="U8" index="1" value="11">



Each element should be represented as a class. Attributes of the elements can be the properties of the equivalent class. Each child element shall again be a property of the parent.
For Ex : for element "Command006" , class structure may look like this.

Class Command006
{
public string name;
public Input input;
public Output output;
}

where in Input and Output are again in turn classes.
Hope this will help you out.

This is not "convert". You need to deserialize XML data.

Do you have XML schema for the file already defined? Can you change it? If you could, I would say, use Data Contract (http://msdn.microsoft.com/en-us/library/ms733127.aspx[^]). It would automatically serialize/deserialize any object graphs consisting of any data types, not necessarily tree, in a standard manner. The file "format" would be created on the fly.

If the XML data is already given, you will need to code it more or less manually. There are several different ways:


  1. Use System.Xml.XmlDocument class. It implements DOM interface; this way is the easiest and good enough if the size if the document is not too big.
    See http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.aspx[^].
  2. Use the class System.Xml.XmlTextReader; this is the fastest way of reading, especially is you need to skip some data.
    See http://msdn.microsoft.com/en-us/library/system.xml.xmlreader.aspx[^].
  3. Use the class System.Xml.Linq.XDocument; this is the most adequate way similar to that of XmlDocument, supporting LINQ to XML Programming.
    See http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.aspx[^], http://msdn.microsoft.com/en-us/library/bb387063.aspx[^].


—SA
 
Share this answer
 
v2
Comments
yesotaso 24-May-11 13:42pm    
As expected :) 5
Sergey Alexandrovich Kryukov 24-May-11 14:10pm    
Thank you very much.
--SA
SaiprasadVernekar 25-May-11 0:22am    
Thanks for your answer. I appreciate it. The requirement for me is to take an .xml file as input and produce an .cs file as output. I believe in Serialization/Deserialization, we need to have the class file defined, prior to conversion, which actually will match the .xml file structure. This is not my requirement. I don't wan to code for the class files, but i want to auto generate it as XSD.EXE tool does from the schema file.
With respect to schema file, yes, we have it and we can change as per our requirement.
Sergey Alexandrovich Kryukov 25-May-11 3:40am    
It's a big step further -- code generation. You should realize that this problem does not have a certain solution. What is the expected properties of generated code? How it's mapped to XML. Also note that data represented in C# code is meta-data (relative to, say, serialized XML). If your XML is XSD, it would makes sense, if it's something else -- it totally depends on the ***semantic*** of this XML.

I personally suspect your requirements have little sense. Your architect invented all that? I do data modeling and code generation for a big part of my career and I know how to design the meta-data engine in different approaches.

We can discuss this, but you need to think on what I just said...
--SA
SaiprasadVernekar 25-May-11 4:36am    
Thanks for your comment. This approach is still under feasibility study. Its not frozen yet. If this is not feasible or if it takes a prolong amount of time then i will have to consider on alternative approaches(right now don't have any other). Frankly speaking, I personally thought that I should go and code for this "Code Generation".
Well thanks for your support. At least you helped me to narrow down my approach. I shall come back with my queries.
To begin with, I think you should have a common schema file that applies all of the XML files. Then you may get better results from the XSD tool. But you should not overestimate its capabilities as it completely ignores the content-inner text-attribute values etc and targets tag/attribute names to generate the corresponding code.
If you are looking for more customised approach look for text generation methods. Ruby erb is one of the powerful ones that I know. For instance
Generator.rb
Ruby
require 'erb'
require 'rexml/document'
include REXML

def subClsHdr (superName,clsNode)
  fh = File.open("header.erb", "r" )
  eruby_script_header = fh.read
  fc = File.open("source.erb", "r" )
  eruby_script_cpp = fc.read
  name = clsNode.attributes['Name']
  fhw = File.open("#{name}.h","w")
  fcw = File.open("#{name}.cpp","w")
  fields = []
  clsNode.elements.each('Field'){|f|
    fields.push( [f.attributes['Type'], f.attributes['Name']]) }
  clsNode.elements.each('Class'){|f| subClsHdr(name,f)}
  erb = ERB.new(eruby_script_header)
  code = erb.result( binding )
  fhw.print code
  fhw.close
  erb = ERB.new(eruby_script_cpp)
  code = erb.result( binding )
  fcw.print code
  fcw.close
end

file = File.new("test.xml")
doc = Document.new(file)
doc.elements.each('Class'){|t| subClsHdr("",t)}

header.erb
/** Author: yesotaso
  * File: "<%= name.capitalize %>.h"
  * Creation Date: <%= Time.now.to_s %>
  * This file is created by automated code generation script
  * via reading xml input. Any changes made will disappear
  * upon next code generation.
  */
#ifndef <%= name.upcase %>_H_
#define <%= name.upcase %>_H_<%if superName.length > 0 %>
#include "<%= superName %>.h"<%end%>
#ifndef COMMONS_H_
    #include "Commons.h"
#endif
class <%= name %><%if superName.length > 0 %> : public <%= superName %><% end %>
{
public:
    <%= name %>();
    virtual ~<%= name %>();
<%fields.each{|l|%> const <%=l[0]%> get<%=l[1].capitalize%>();
    void set<%=l[1].capitalize%>(const <%=l[0]%>& param);<%}%>
private:
<%fields.each{|l|%> <%=l[0]%> <%=l[1]%>;<%}%>};
#endif //<%= name.upcase %>_H_

And input
XML
<Class Name="Person">
    <Field Name="Name" Type="std::string"></Field>
    <Field Name="Status" Type="std::string"></Field>
    <Field Name="Age" Type="int"></Field>
    <Class Name="Worker">
        <Field Name="ssid" Type="int"></Field>
        <Class Name="Banker">
            <Field Name="Position" Type="std::string"></Field>
        </Class>
    </Class>
</Class>

The output "Person.h":
C++
/** Author: yesotaso
  * File: "Person.h"
  * Creation Date: xxxxxxxxxxxxxxx
  * This file is created by automated code generation script
  * via reading xml input. Any changes made will disappear
  * upon next code generation.
  */
#ifndef PERSON_H_
#define PERSON_H_
#ifndef COMMONS_H_
    #include "Commons.h"
#endif
class Person
{
public:
    Person();
    virtual ~Person();
    const std::string getName();
    void setName(const std::string& param);
    const std::string getStatus();
    void setStatus(const std::string& param);
    const int getAge();
    void setAge(const int& param);
private:
    std::string Name;
    std::string Status;
    int Age;
};
#endif //PERSON_H_

Output "Worker.h":
C++
/** Author: yesotaso
  * File: "Worker.h"
  * Creation Date: xxxxxxxxxxxxx
  * This file is created by automated code generation script
  * via reading xml input. Any changes made will disappear
  * upon next code generation.
  */
#ifndef WORKER_H_
#define WORKER_H_
#include "Person.h"
#ifndef COMMONS_H_
	#include "Commons.h"
#endif
class Worker : public Person
{
public:
	Worker();
	virtual ~Worker();
	const int getSsid();
	void setSsid(const int& param);
private:
	int ssid;
};
#endif //WORKER_H_

And so on with corresponding "cpp" files etc. You can of course go for Linq to Xml or some other way whichever fits your taste.
Hope it helps.
 
Share this answer
 
v2
Comments
Sergey Alexandrovich Kryukov 24-May-11 14:13pm    
I voted 5 just to show it's interesting to attract attention to Ruby, but don't you think it's way too far from the topic? And just installing and further support of yet another language could be an extra hassle and risk. If you badly want to promote Ruby, it may be a way, but...
--SA
yesotaso 24-May-11 14:20pm    
Thanks. It was not my first intetion to to promote Ruby but to give an interesting alternative, in the end well yes I did...
My point is do not expect everything from the tools, there are alternatives for which you should look around and make use of them to widen vision.
Edit: For the topic I dont think it is offly unrelated, for the risk it wouldnt be any more than trying to learn another code library. Besides it is open-source interpreter there is no licence hassle :)
Sergey Alexandrovich Kryukov 24-May-11 22:56pm    
Understand your reasons...
Thank you for this discussion.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900