Creating XML file with schema

I am working with XML file which looks like:

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ELEMENT Student ANY>
  <!ATTLIST Student ID ID #REQUIRED>
]>
<Students>
  <Student ID="104">
    <Name>Vicki Tyson</Name>
     <Grades>
       <MFC>48</MFC>
       <ATL>63</ATL>
       <Winsock>72</Winsock>
    </Grades>
  </Student>
  ...
</Students>

I have the program that can open, update and save files with such structure. It works by such way:

XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(fileName);   // now document contains both data and schema
// make changes in XmlDocument ...
xmlDocument.Save(fileName);

Saved document contains both schema and data. Now I want to add "New" function to the program, which creates new file. In this case program should work by such way:

XmlDocument xmlDocument = new XmlDocument();
// make changes in XmlDocument (add nodes)
xmlDocument.Save(fileName);

However, document created by such way doesn't contain schema. How can I add XML schema programmatically?
LVL 48
AlexFMAsked:
Who is Participating?
 
ee_ai_constructConnect With a Mentor Commented:
Closed, 500 points refunded.
ee_ai_construct
Community Support Moderator
(re-order part number xm34)
0
 
Bob LearnedCommented:
There are tutorials for XML schema documents:

XSD How To
http://www.w3schools.com/schema/schema_howto.asp

You could start with these, and learn the syntax rules.  And then look at an XSD file generated for a typed dataset by a DataAdapter.

These nodes are from an existing XSD:

 <?xml version="1.0" standalone="yes" ?>
- <xs:schema id="DataSet1" targetNamespace="http://www.tempuri.org/DataSet1.xsd" xmlns:mstns="http://www.tempuri.org/DataSet1.xsd" xmlns="http://www.tempuri.org/DataSet1.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" attributeFormDefault="qualified" elementFormDefault="qualified">
- <xs:element name="DataSet1" msdata:IsDataSet="true">
- <xs:complexType>


Bob
0
 
vascovCommented:
DataSet ds = new DataSet();

ds.ReadXml( fileName );

MessageBox.Show( ds.GetXmlSchema() )


Another way... drop your file in VS.NET, and then right-click on the xml content and select "Generate Schema". From then on tweak that schema.
(if you want, you can further generate a strong typed dataset (right-click on the schema, and "Generate DataSet", or you can also use the cmd-line xsd.exe)

hth

Vasco
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
AlexFMAuthor Commented:
Thanks, but both answers are not related to my question. I don't need to learn XML schema structure, and I don't work with dataset.
My question is: having XmlDocument instance, how can I add to it XML schema programmatically?
I think this is possible, because when XmlDocument instance loads file which contains schema, it keeps it and writes the same schema to file created by Save function.
0
 
vascovCommented:
Alex, Schema is used to validate a given document, not to prepopulate or something like that.
If all you want is to generate a new schema,
* create a DataSet
* Load the xml from the XmlDocument and ask to save it as:

DataSet ds = new DataSet();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml( "<root/>" );
xmlDoc.DocumentElement.Attributes.Append( xmlDoc.CreateAttribute( "abc", "http://mynamespace" ) );
StringReader sr = new StringReader( xmlDoc.InnerXml );
ds.ReadXml( sr, XmlReadMode.Auto );
StringWriter sw = new StringWriter();
ds.WriteXml( sw, XmlWriteMode.WriteSchema );
MessageBox.Show( sw.ToString() );

hth

Vasco
0
 
AlexFMAuthor Commented:
Well, I try to ask again.
Suppose I have such XML file:

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ELEMENT Student ANY>
  <!ATTLIST Student ID ID #REQUIRED>
]>
<Students>
  <Student ID="104">
    <Name>Vicki Tyson</Name>
     <Grades>
       <MFC>48</MFC>
       <ATL>63</ATL>
       <Winsock>72</Winsock>
    </Grades>
  </Student>
</Students>

Program:

XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(fileName);   // now document contains both data and schema
// add new node to XML document ...
xmlDocument.Save(fileName);

Result:

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ELEMENT Student ANY>
  <!ATTLIST Student ID ID #REQUIRED>
]>
<Students>
  <Student ID="104">
    <Name>Vicki Tyson</Name>
     <Grades>
       <MFC>48</MFC>
       <ATL>63</ATL>
       <Winsock>72</Winsock>
    </Grades>
  </Student>
  <Student ID="105">
    <Name>John</Name>
     <Grades>
       <MFC>48</MFC>
       <ATL>63</ATL>
       <Winsock>72</Winsock>
    </Grades>
  </Student>
</Students>

Other situation: I don't have XML file. Program:

XmlDocument xmlDocument = new XmlDocument();
// add new node to XML document ...
xmlDocument.Save(fileName);

Result:

<?xml version="1.0"?>
<Students>
  <Student ID="105">
    <Name>John</Name>
     <Grades>
       <MFC>48</MFC>
       <ATL>63</ATL>
       <Winsock>72</Winsock>
    </Grades>
  </Student>
</Students>

I want this result:

<?xml version="1.0"?>
<!DOCTYPE root [
  <!ELEMENT Student ANY>
  <!ATTLIST Student ID ID #REQUIRED>
]>
<Students>
  <Student ID="105">
    <Name>John</Name>
     <Grades>
       <MFC>48</MFC>
       <ATL>63</ATL>
       <Winsock>72</Winsock>
    </Grades>
  </Student>
</Students>

I want to do this programmatically:

XmlDocument xmlDocument = new XmlDocument();
// add schema to XML document - how ???
// add new node to XML document ...
xmlDocument.Save(fileName);
0
 
vascovCommented:
Hi Alex, the sample i sent you does just that.
It will generate Xml Schema though, and i frankly don't know how/if it can generate DTD. (i'm under the impression it wont)

For the sample i sent you before, here's the output:
<NewDataSet>
  <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:app1="http://mynamespace">
    <!--ATTENTION: This schema contains references to other imported schemas-->
    <xs:import namespace="http://mynamespace" schemaLocation="_app1.xsd" />
    <xs:element name="root">
      <xs:complexType>
        <xs:attribute ref="app1:abc" />
      </xs:complexType>
    </xs:element>
    <xs:element name="NewDataSet" msdata:IsDataSet="true">
      <xs:complexType>
        <xs:choice maxOccurs="unbounded">
          <xs:element ref="root" />
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <root d1p1:abc="" xmlns:d1p1="http://mynamespace" />
</NewDataSet>


Vasco
0
 
AlexFMAuthor Commented:
Thanks, I found sirprisingly simple way to do this using XmlDocument.LoadXml function.
0
 
Bob LearnedCommented:
Could you explain how you did it in more detail?

Bob
0
 
vascovCommented:
I'm also interested,

do you mean that you used XmlDocument.LoadXml to generate inline DTD ?

Vasco
0
 
vascovCommented:
I don't object closing the question, but i think that an explanation of how (and what) it was solved should be given by Alex.

My suspicion is that Alex used LoadXml do inline the DTD himself, but i'm still curious if that's his question.
If you ended up using LoadXml for that, than i'm glad that eventually my sample hinted you in that direction.

Furthermore, if all you wanted was to generate the DTD yourself than look at XmlDocument.CreateDocumentType...

Vasco

0
 
AlexFMAuthor Commented:
This is my code:

        public bool NewDocument()
        {
            try
            {
                xmlDocument = new XmlDocument();

                StringBuilder s = new StringBuilder();
                s.Append("<?xml version=\"1.0\"?>\n");
                s.Append("<!DOCTYPE root[\n");
                s.Append("  <!ELEMENT Student ANY>\n");
                s.Append(" <!ATTLIST Student ID ID #REQUIRED>\n");
                s.Append("]>\n");
                s.Append("<Students>\n");
                s.Append("</Students>");

                xmlDocument.LoadXml(s.ToString());

                fileName = "";
                SetDirty(false);
                RaiseStateChangeEvent();

                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(parentForm, String.Format(ex.Message), errorTitle);
            }

            return false;
        }

I know this question looks stupid, and external XML schema should be used instead of inline DTD, but this is what I needed to complete my XML exersize. Thank you for your help, if somebody thinks that his notes were helpful, you can post here and I will accept them.
0
All Courses

From novice to tech pro — start learning today.