XmlWriter writer, DataTableCollection tables,
DataRelationCollection relations)
{
- ds = dataset;
+ dataSetName = dataset.DataSetName;
+ dataSetNamespace = dataset.Namespace;
+ dataSetLocale = dataset.Locale;
+ dataSetProperties = dataset.ExtendedProperties;
+ w = writer;
+ if (tables != null) {
+ this.tables = new DataTable[tables.Count];
+ for(int i=0;i<tables.Count;i++) this.tables[i] = tables[i];
+ }
+ if (relations != null) {
+ this.relations = new DataRelation[relations.Count];
+ for(int i=0;i<relations.Count;i++) this.relations[i] = relations[i];
+ }
+ }
+
+ public XmlSchemaWriter (XmlWriter writer,
+ DataTable[] tables,
+ DataRelation[] relations,
+ string mainDataTable,
+ string dataSetName)
+ {
w = writer;
this.tables = tables;
this.relations = relations;
+ this.mainDataTable = mainDataTable;
+ this.dataSetName = dataSetName;
+ this.dataSetProperties = new PropertyCollection();
+ if (tables[0].DataSet != null) {
+ dataSetNamespace = tables[0].DataSet.Namespace;
+ dataSetLocale = tables[0].DataSet.Locale;
+ } else {
+ dataSetNamespace = tables[0].Namespace;
+ dataSetLocale = tables[0].Locale;
+ }
}
- DataSet ds;
XmlWriter w;
- DataTableCollection tables;
- DataRelationCollection relations;
+ DataTable[] tables;
+ DataRelation[] relations;
+ string mainDataTable;
+ string dataSetName;
+ string dataSetNamespace;
+ PropertyCollection dataSetProperties;
+ CultureInfo dataSetLocale;
ArrayList globalTypeTables = new ArrayList ();
Hashtable additionalNamespaces = new Hashtable ();
+ ArrayList annotation = new ArrayList ();
+
public string ConstraintPrefix {
- get { return ds.Namespace != String.Empty ? XmlConstants.TnsPrefix + ':' : String.Empty; }
+ get { return dataSetNamespace != String.Empty ? XmlConstants.TnsPrefix + ':' : String.Empty; }
}
// the whole DataSet
}
w.WriteStartElement ("xs", "schema", xmlnsxs);
- w.WriteAttributeString ("id", XmlConvert.EncodeLocalName (ds.DataSetName));
+ w.WriteAttributeString ("id", XmlHelper.Encode (dataSetName));
- if (ds.Namespace != String.Empty) {
+ if (dataSetNamespace != String.Empty) {
w.WriteAttributeString ("targetNamespace",
- ds.Namespace);
+ dataSetNamespace);
w.WriteAttributeString (
"xmlns",
XmlConstants.TnsPrefix,
XmlConstants.XmlnsNS,
- ds.Namespace);
+ dataSetNamespace);
}
- w.WriteAttributeString ("xmlns", ds.Namespace);
+ w.WriteAttributeString ("xmlns", dataSetNamespace);
w.WriteAttributeString ("xmlns", "xs",
XmlConstants.XmlnsNS, xmlnsxs);
XmlConstants.XmlnsNS,
XmlConstants.MspropNamespace);
- if (ds.Namespace != String.Empty) {
+ if (dataSetNamespace != String.Empty) {
w.WriteAttributeString ("attributeFormDefault", "qualified");
w.WriteAttributeString ("elementFormDefault", "qualified");
}
private void WriteDataSetElement ()
{
w.WriteStartElement ("xs", "element", xmlnsxs);
- w.WriteAttributeString ("name", XmlConvert.EncodeLocalName (ds.DataSetName));
+ w.WriteAttributeString ("name", XmlHelper.Encode (dataSetName));
w.WriteAttributeString (XmlConstants.MsdataPrefix,
"IsDataSet", XmlConstants.MsdataNamespace,
"true");
+
+ if(mainDataTable != null && mainDataTable != "")
+ w.WriteAttributeString (
+ XmlConstants.MsdataPrefix,
+ "MainDataTable",
+ XmlConstants.MsdataNamespace,
+ mainDataTable);
#if NET_2_0
- if (ds.Locale == CultureInfo.CurrentCulture) {
+ if (dataSetLocale == CultureInfo.CurrentCulture) {
w.WriteAttributeString (
XmlConstants.MsdataPrefix,
"UseCurrentCulture",
XmlConstants.MsdataPrefix,
"Locale",
XmlConstants.MsdataNamespace,
- ds.Locale.Name);
+ dataSetLocale.Name);
}
- AddExtendedPropertyAttributes (ds.ExtendedProperties);
+ AddExtendedPropertyAttributes (dataSetProperties);
w.WriteStartElement ("xs", "complexType", xmlnsxs);
w.WriteStartElement ("xs", "choice", xmlnsxs);
}
if (isTopLevel) {
- if (ds.Namespace != table.Namespace) {
+ if (dataSetNamespace != table.Namespace) {
// <xs:element ref="X:y" />
w.WriteStartElement ("xs",
"element",
xmlnsxs);
w.WriteStartAttribute ("ref", String.Empty);
- w.WriteQualifiedName (XmlConvert.EncodeLocalName (table.TableName), table.Namespace);
+ w.WriteQualifiedName (XmlHelper.Encode (table.TableName), table.Namespace);
w.WriteEndAttribute ();
w.WriteEndElement ();
}
WriteConstraints (); // DataSet constraints
w.WriteEndElement (); // element
+
+ if (annotation.Count > 0) {
+ w.WriteStartElement ("xs", "annotation", xmlnsxs);
+ w.WriteStartElement ("xs", "appinfo", xmlnsxs);
+
+ foreach (object o in annotation) {
+ if (!(o is DataRelation))
+ continue;
+ WriteDataRelationAnnotation ((DataRelation)o);
+ }
+ w.WriteEndElement ();
+ w.WriteEndElement ();
+ }
}
- // Relation based Constraints
+ private void WriteDataRelationAnnotation (DataRelation rel)
+ {
+ String colnames = String.Empty;
+ w.WriteStartElement (XmlConstants.MsdataPrefix, "Relationship",
+ XmlConstants.MsdataNamespace);
+
+ w.WriteAttributeString ("name", XmlHelper.Encode (rel.RelationName));
+
+ w.WriteAttributeString (
+ XmlConstants.MsdataPrefix,
+ "parent",
+ XmlConstants.MsdataNamespace,
+ XmlHelper.Encode (rel.ParentTable.TableName));
+
+ w.WriteAttributeString (
+ XmlConstants.MsdataPrefix,
+ "child",
+ XmlConstants.MsdataNamespace,
+ XmlHelper.Encode (rel.ChildTable.TableName));
+
+ colnames = String.Empty;
+ foreach (DataColumn col in rel.ParentColumns)
+ colnames += XmlHelper.Encode (col.ColumnName) + " ";
+ w.WriteAttributeString (
+ XmlConstants.MsdataPrefix,
+ "parentkey",
+ XmlConstants.MsdataNamespace,
+ colnames.TrimEnd ());
+
+ colnames = String.Empty;
+ foreach (DataColumn col in rel.ChildColumns)
+ colnames += XmlHelper.Encode (col.ColumnName) + " ";
+ w.WriteAttributeString (
+ XmlConstants.MsdataPrefix,
+ "childkey",
+ XmlConstants.MsdataNamespace,
+ colnames.TrimEnd ());
+
+ w.WriteEndElement ();
+ }
private void WriteConstraints ()
{
foreach (Constraint c in table.Constraints) {
UniqueConstraint u =
c as UniqueConstraint;
- if (u != null)
+ if (u != null) {
AddUniqueConstraints (u, names);
+ continue;
+ }
+
+ ForeignKeyConstraint fk = c as ForeignKeyConstraint;
+ bool haveConstraint = false;
+ if (relations != null)
+ foreach (DataRelation r in relations)
+ if(r.RelationName == fk.ConstraintName)
+ haveConstraint = true;
+ if (fk != null && !haveConstraint) {
+ DataRelation rel = new DataRelation (fk.ConstraintName,
+ fk.RelatedColumns, fk.Columns);
+ AddForeignKeys (rel, names, true);
+ continue;
+ }
}
}
// Add all foriegn key constraints.
if (relations != null)
- foreach (DataRelation rel in relations)
- if (rel.ParentKeyConstraint != null &&
- rel.ChildKeyConstraint != null)
- AddForeignKeys (rel, names);
+ foreach (DataRelation rel in relations) {
+ if (rel.ParentKeyConstraint == null || rel.ChildKeyConstraint == null) {
+ annotation.Add (rel);
+ continue;
+ }
+ AddForeignKeys (rel, names,false);
+ }
}
// Add unique constaraints to the schema.
// if constaraint name do not exist in the hashtable we can use it.
string name;
if (!names.Contains (uniq.ConstraintName)) {
- name = uniq.ConstraintName;
+ name = XmlHelper.Encode (uniq.ConstraintName);
w.WriteAttributeString ("name", name);
}
// otherwise generate new constraint name for the
// XmlSchemaUnique element.
else {
- name = XmlConvert.EncodeLocalName (uniq.Table.TableName) + "_" + uniq.ConstraintName;
+ name = XmlHelper.Encode (uniq.Table.TableName) + "_" + XmlHelper.Encode (uniq.ConstraintName);
w.WriteAttributeString ("name", name);
w.WriteAttributeString (
XmlConstants.MsdataPrefix,
XmlConstants.ConstraintName,
XmlConstants.MsdataNamespace,
- uniq.ConstraintName);
+ XmlHelper.Encode (uniq.ConstraintName));
}
names.Add (name);
w.WriteStartElement ("xs", "selector",
xmlnsxs);
w.WriteAttributeString ("xpath", ".//" +
- ConstraintPrefix + XmlConvert.EncodeLocalName (uniq.Table.TableName));
+ ConstraintPrefix + XmlHelper.Encode (uniq.Table.TableName));
w.WriteEndElement (); // selector
foreach (DataColumn c in uniq.Columns) {
w.WriteStartElement ("xs", "field",
if (c.ColumnMapping == MappingType.Attribute)
w.WriteString ("@");
w.WriteString (ConstraintPrefix);
- w.WriteString (XmlConvert.EncodeLocalName (c.ColumnName));
+ w.WriteString (XmlHelper.Encode (c.ColumnName));
w.WriteEndAttribute (); // xpath
w.WriteEndElement (); // field
}
}
// Add the foriegn keys to the schema.
- private void AddForeignKeys (DataRelation rel, ArrayList names)
+ private void AddForeignKeys (DataRelation rel, ArrayList names, bool isConstraintOnly)
{
// Do nothing if it contains hidden relation
foreach (DataColumn col in rel.ParentColumns)
return;
w.WriteStartElement ("xs", "keyref", xmlnsxs);
- w.WriteAttributeString ("name", XmlConvert.EncodeLocalName (rel.RelationName));
+ w.WriteAttributeString ("name", XmlHelper.Encode (rel.RelationName));
+
+ //ForeignKeyConstraint fkConst = rel.ChildKeyConstraint;
+ UniqueConstraint uqConst = null;
- ForeignKeyConstraint fkConst = rel.ChildKeyConstraint;
- UniqueConstraint uqConst = rel.ParentKeyConstraint;
+ if (isConstraintOnly) {
+ foreach (Constraint c in rel.ParentTable.Constraints) {
+ uqConst = c as UniqueConstraint;
+ if (uqConst == null)
+ continue;
+ if (uqConst.Columns == rel.ParentColumns)
+ break;
+ }
+ }
+ else
+ uqConst = rel.ParentKeyConstraint;
- string concatName = XmlConvert.EncodeLocalName (rel.ParentTable.TableName) + "_" + uqConst.ConstraintName;
+ string concatName = XmlHelper.Encode (rel.ParentTable.TableName) + "_" + XmlHelper.Encode (uqConst.ConstraintName);
// first try to find the concatenated name. If we didn't find it - use constraint name.
if (names.Contains (concatName)) {
w.WriteStartAttribute ("refer", String.Empty);
- w.WriteQualifiedName (concatName, ds.Namespace);
+ w.WriteQualifiedName (concatName, dataSetNamespace);
w.WriteEndAttribute ();
}
else {
w.WriteStartAttribute ("refer", String.Empty);
- w.WriteQualifiedName (
- uqConst.ConstraintName, ds.Namespace);
+ w.WriteQualifiedName (XmlHelper.Encode (uqConst.ConstraintName), dataSetNamespace);
w.WriteEndAttribute ();
}
- if (rel.Nested)
+ if (isConstraintOnly)
+ w.WriteAttributeString ( XmlConstants.MsdataPrefix,
+ XmlConstants.ConstraintOnly,
+ XmlConstants.MsdataNamespace,
+ "true");
+ else if (rel.Nested)
w.WriteAttributeString (
XmlConstants.MsdataPrefix,
XmlConstants.IsNested,
w.WriteStartElement ("xs", "selector", xmlnsxs);
w.WriteAttributeString ("xpath", ".//" +
- ConstraintPrefix + XmlConvert.EncodeLocalName (rel.ChildTable.TableName));
+ ConstraintPrefix + XmlHelper.Encode (rel.ChildTable.TableName));
w.WriteEndElement ();
foreach (DataColumn c in rel.ChildColumns) {
if (c.ColumnMapping == MappingType.Attribute)
w.WriteString ("@");
w.WriteString (ConstraintPrefix);
- w.WriteString (XmlConvert.EncodeLocalName (c.ColumnName));
+ w.WriteString (XmlHelper.Encode (c.ColumnName));
w.WriteEndAttribute ();
w.WriteEndElement (); // field
}
// ExtendedProperties
private bool CheckExtendedPropertyExists (
- DataTableCollection tables,
- DataRelationCollection relations)
+ DataTable[] tables,
+ DataRelation[] relations)
{
- if (ds.ExtendedProperties.Count > 0)
+ if (dataSetProperties.Count > 0)
return true;
foreach (DataTable dt in tables) {
if (dt.ExtendedProperties.Count > 0)
private void WriteTableElement (DataTable table)
{
w.WriteStartElement ("xs", "element", xmlnsxs);
- w.WriteAttributeString ("name", XmlConvert.EncodeLocalName (table.TableName));
+ w.WriteAttributeString ("name", XmlHelper.Encode (table.TableName));
AddExtendedPropertyAttributes (table.ExtendedProperties);
// add column name attribute
w.WriteAttributeString (
XmlConstants.MsdataPrefix,
- XmlConvert.EncodeLocalName (XmlConstants.ColumnName),
+ XmlConstants.ColumnName,
XmlConstants.MsdataNamespace,
- XmlConvert.EncodeLocalName (simple.ColumnName));
+ XmlHelper.Encode (simple.ColumnName));
// add ordinal attribute
w.WriteAttributeString (
if (elements.Count > 0) {
w.WriteStartElement ("xs", "sequence",
xmlnsxs);
+
foreach (DataColumn col in elements)
- WriteTableTypeParticles (
- col);
+ WriteTableTypeParticles (col);
+
+ foreach (DataRelation rel in table.ChildRelations)
+ if (rel.Nested)
+ WriteChildRelations (rel);
w.WriteEndElement ();
}
-
- foreach (DataRelation rel in table.ChildRelations)
- if (rel.Nested)
- WriteChildRelations (rel);
}
w.WriteFullEndElement (); // complexType
private void WriteTableTypeParticles (DataColumn col)
{
- w.WriteStartElement ("xs", "element",
- xmlnsxs);
- w.WriteAttributeString ("name",
- XmlConvert.EncodeLocalName (col.ColumnName));
+ w.WriteStartElement ("xs", "element", xmlnsxs);
+ w.WriteAttributeString ("name", XmlHelper.Encode (col.ColumnName));
if (col.ColumnName != col.Caption && col.Caption != String.Empty)
w.WriteAttributeString (
private void WriteChildRelations (DataRelation rel)
{
- if (rel.ChildTable.Namespace != ds.Namespace) {
+ if (rel.ChildTable.Namespace != dataSetNamespace) {
w.WriteStartElement ("xs", "element", xmlnsxs);
w.WriteStartAttribute ("ref", String.Empty);
w.WriteQualifiedName (
- XmlConvert.EncodeLocalName (rel.ChildTable.TableName),
+ XmlHelper.Encode (rel.ChildTable.TableName),
rel.ChildTable.Namespace);
w.WriteEndAttribute ();
} else {
w.WriteStartElement ("xs", "element", xmlnsxs);
- w.WriteStartAttribute ("type", String.Empty);
+ w.WriteStartAttribute ("name", String.Empty);
w.WriteQualifiedName (
- XmlConvert.EncodeLocalName (rel.ChildTable.TableName),
+ XmlHelper.Encode (rel.ChildTable.TableName),
rel.ChildTable.Namespace);
w.WriteEndAttribute ();
- w.WriteEndElement ();
-
- globalTypeTables.Add (rel.ChildTable);
w.WriteAttributeString ("minOccurs", "0");
w.WriteAttributeString ("maxOccurs", "unbounded");
+
+ globalTypeTables.Add (rel.ChildTable);
}
+ WriteTableType (rel.ChildTable);
+ w.WriteEndElement ();
}
private void WriteTableAttributes (ArrayList atts)
foreach (DataColumn col in atts) {
w.WriteStartElement ("xs", "attribute", xmlnsxs);
- string name = XmlConvert.EncodeLocalName (col.ColumnName);
+ string name = XmlHelper.Encode (col.ColumnName);
if (col.Namespace != String.Empty) {
w.WriteAttributeString ("form", "qualified");
string prefix = col.Prefix == String.Empty ? "app" + additionalNamespaces.Count : col.Prefix;
{
if (ns == String.Empty)
return;
- if (ds.Namespace != ns) {
- if (names [prefix] != ns) {
+ if (dataSetNamespace != ns) {
+ if ((string)names [prefix] != ns) {
for (int i = 1; i < int.MaxValue; i++) {
string p = "app" + i;
if (names [p] == null) {