block invalid elements XSD? - c#

I have a simple XSD:
<xs:element name="config">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="group" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
On my xml file i put this:
<config>
<group></group>
<a></a>
</config>
How block the insertion of <a> tag on my xml?
Obs: group appears on auto-complete on my C# xml editor!!!

You cannot "block" the insertion of the <a> unless you write a XML editor yourself which would understand and interpret the XSD schema on the fly.
What you can do is validate the XML created against the schema and refuse it, if it's not valid.
Marc

Sounds to me like that tag you'd like to exclude should be a child of the "config" tag, just like group. If it has a relationship with "config", and should only appear if its parent does, you need to express it.

Problem Resolved!!
Is a error on my Visual Studio Express Edition
The Visual Studio 2008 (Full Version) process XSD correctly!!
Thanks for all!!

Related

How do you create an XML document from an XSD Schema at runtime in modern c#? [duplicate]

I have searched for a bit now, but i'm not able to find a way to autogenerate data from a XML Schema programmatically. Lets say I have this XML schema:
<xs:element xmlns:xs="http://www.w3.org/2001/XMLSchema" name ="Persons">
<xs:complexType>
<xs:sequence>
<xs:element name="Person">
<xs:complexType>
<xs:sequence>
<xs:element name="FirstName" type="xs:string" />
<xs:element name="LastName" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
I am able to create a XML from this using the VS function "Generate Sample XML"
Is there a way to do this programmatically?
Edit: To specify. I do not want to create all the objects and insert data programmatically myself. I would like for it to create the objects and attributes automatically just like the "Generate Sample XML" in VS. The reason for this is that i would like to change the XSD without having to do anything about xml sample generation.
after doing some searching. I have found a project that have implemented a xml sample generator. I created a test solution and imported the classes. Then i deleted the XmlGen.cs file and created my own main method. The output will be based on the root element.
public static void Main(string[] args)
{
using (var stream = new MemoryStream(File.ReadAllBytes("schema.xsd")))
{
var schema = XmlSchema.Read(XmlReader.Create(stream ), null);
var gen = new XmlSampleGenerator(schema, new XmlQualifiedName("rootElement"));
gen.WriteXml(XmlWriter.Create(#"c:\temp\autogen.xml"));
Console.WriteLine("Autogenerated file is here : c:\temp\autogen.xml");
}
}
You can write simple function for put 1 row into your data table and after that execute DataTable.WriteXml(string filePath)
Somethig like that:
xmlschema1 schema=new xmlschema1();
//put some test data in table
schema.Persons.AddPersonsRow(...some params);
//generate xml
schema.Persons.WriteXml(filePath);

How to update the different XML element simultaneously by multiple users in single XML file?

I have one XML File:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<NewDataSet>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" <xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="UsersPreferenceSettingsDT">
<xs:complexType>
<xs:sequence>
<xs:element name="USERPROFILEID" type="xs:int" minOccurs="0" />
<xs:element name="SCREENAMEID" type="xs:int" minOccurs="0" />
<xs:element name="FREEZEDCOLUMNID" type="xs:string" minOccurs="0" />
<xs:element name="ORDEROFCOLUMNS" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<UsersPreferenceSettingsDT>
<USERPROFILEID>219</USERPROFILEID>
<SCREENAMEID>1</SCREENAMEID>
<FREEZEDCOLUMNID>2|3|4|5</FREEZEDCOLUMNID>
<ORDEROFCOLUMNS>1</ORDEROFCOLUMNS>
</UsersPreferenceSettingsDT>
<UsersPreferenceSettingsDT>
<USERPROFILEID>123</USERPROFILEID>
<SCREENAMEID></SCREENAMEID>
<FREEZEDCOLUMNID>s|s|s</FREEZEDCOLUMNID>
<ORDEROFCOLUMNS></ORDEROFCOLUMNS>
</UsersPreferenceSettingsDT>
</NewDataSet>
In that i have to update the XML Element (i,e USERPROFILeID =219, USERPROFILEID is Unique). At same time another user also update the same XML file but different XML element (i,e USERPROFILEID=123). How can the XML reflect the both users XML update(Like SQL or ORACLE DB Update). I used the following code to update.
userPreferenceSettingsDS.WriteXml(userPreferenceSettingsXMLFilePath, XmlWriteMode.WriteSchema);
but it reflect the last user profile update Value only , while multiple user simultaneously update the XML. Anyone guide me to come out of these issue?
Well, being that we are talking about an xml file and not a database you will not be able to get the "latest" version of the data unless you always load from file and not from memory but even then you expose yourself to concurrency issues.
The best choice here would be to switch to a database or maybe implement something like a Singleton Repository that would serve all users and that way you will always return the latest values of the data in the xml.
And it would fix your other issue, when you write to file you will write the "merged" version of the data that will contain changes from multiple users.
Resources for XML as database:
http://social.msdn.microsoft.com/Forums/en/sqldataaccess/thread/346a2816-faae-461d-aaa8-235d9c0dd55c
XML Database in C#.net
http://bytes.com/topic/c-sharp/answers/460625-c-pure-xml-database
Or use a single profile file per user.
You would need to ensure that only one save operation can happen at a time.
To do this, you need to provide a static (shared) class that reads from and writes to the file. The fancy new buzzword for this is a Singleton instance, but it's simply the following:
public static class MyXMLAccessor
{
public static void saveTheData()
{
//this method would write the data to the XML file and save it.
}
public static string ReadTheData()
{
//to read the data from the file
}
}
This way, you're guaranteed that the result of one operation is saved before the next operation is started.
A more complex solution would be to read the xml into an application-scope dataset so that it can act like a database. You would then periodically write the contents of the dataset back to a file using the DataSet.ToXML() method.
It sounds to me as if you should be using an XML database. The sooner you make the move, the more benefit you will get from it, and the less you will spend on creating your own inadequate home-grown solution.

XML serialization with c# & windows forms

I am trying to create a waypoint generator using windows forms, that allows a user to create waypoint & path data via a GUI & output the data to an XML file. I've chosen to take advantage of the built in c# XML serialization feature, but have been unable to format the XML output in the way required by the client.
A stripped version of the waypoint data object would look something like the following:
// Waypoint data class
[XmlRoot("RootNode")]
public class WaypointProjectData
{
[XmlElement("Map")] // Also tried to use XmlElementAttribute,
[XmlAttribute("file")] // XmlAttributeAttribute, and many variations
// of these qualifiers, with no success
public string m_szMapImageFileName;
[XmlAttribute("width")]
public int m_iWidth;
[XmlAttribute("height")]
public int m_iHeight;
[XmlArray("Nodes")]
public ArrayList m_aoNodes;
WaypointProjectData()
{
m_szMapImageFileName = "map.png";
m_aoNodes = new ArrayList();
}
}
The client requires that the XML output conforms with the following layout/format:
<RootNode>
<Map file="map.png" width="100" height="100" />
<OtherData var="variable" data="10" />
<Nodes>
<Node x="10" y="30" />
<Node x="30" y="20" /> // etc...
</Nodes>
</RootNode>
Some clear examples on how to do this using c# xml serialization would be very helpful. Thanks!
When I have to serialize something in a specific Xml format like this, I start with a schema (inferred if necessary, hand-crafted if known). Then I use the VS xsd tool to create the serialization classes (and yes, I know xsd can be used for the inferring schema part—I just never bother with it for that purpose).
So if you have an xsd file like this one created from your example (note that I specified data types as much as possible—this helps the xsd tool to use the appropriate types for properties):
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="RootNode">
<xs:complexType>
<xs:sequence>
<xs:element name="Map">
<xs:complexType>
<xs:attribute name="file" type="xs:string"/>
<xs:attribute name="width" type="xs:decimal"/>
<xs:attribute name="height" type="xs:decimal"/>
</xs:complexType>
</xs:element>
<xs:element name="OtherData">
<xs:complexType>
<xs:attribute name="var" type="xs:string"/>
<xs:attribute name="data" type="xs:decimal"/>
</xs:complexType>
</xs:element>
<xs:element name="Nodes" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="Node" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="x" type="xs:decimal"/>
<xs:attribute name="y" type="xs:decimal"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
If you name this Root.xsd, then you can go to the VS command line and run
xsd Root.xsd /c /n:myProject.Xml
That'll create a class file (named Root.cs because that's the default when processing Root.xsd) that contains objects you can easily plug into .Net to serialize and deserialize the XML. Note that I specified the namespace the classes will have ("/n:myProject.Xml"). I prefer to control that namespace, but defaults are usually fine for the rest. Further, the tool creates partial classes, so if you want custom property accessors, you're fine to add them in a separate file that won't get creamed if you need to run the tool again.
Another tip, I create a text file in my project with the name "<xsd name> xsd Command Line.txt". That way I just have to paste that into the VS command line and don't have to remember everything else I used.
As soon as you go off the beaten track serialisation is a huge PIA.
You need something to mark up as map, probably OtherData as well, so that means you need a class or struct that corresponds to the node.
e.g. WaypointProejctdata as a class Map, that has properties filename, width and height.
My general rule of thumb, is as soon as I have to start messing with my objects to get the xml, serialisation gets binned,and I add an interface that takes an XmlReader or Writer and implement it.
Tryng to get serialisation to do what you want is usually way more code and far less comprehensible than doing that.

WSDL and XSD List declaration

Today I have the folowwing xsd declaration that is generated to Array
<xs:element name="SubNodes" type="Node" minOccurs="0" maxOccurs="unbounded"/>
How can I do something that will be generated to List<> ?
(Using c#)
Update:
I've tried
<xs:simpleType name="SubNodes">
<xs:list itemType="Node"/>
</xs:simpleType>
but got the error:
The 'http://www.w3.org/2001/XMLSchema:simpleType' element is not
supported in this context
What tool are you using to generate the wsdl? I will assume it is visual studio.
In that case when you generate the service reference, click "Advanced" and you should see this screen where you can select the collection type:

Displaying XML schema elements in treeview in order of appearance in XML

I need to display XSD files in a treeview. I already found one solution for this here!, but this just displays all the nodes in the file in the order they appear.
What I need is to display them in the order they appear in the XML file, and nested under the elements they will be nested under in the XML file:
<?xml version="1.0" encoding="IBM437"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="cat" type="xs:string"/>
<xs:element name="dog" type="xs:string"/>
<xs:element name="pets">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="cat"/>
<xs:element ref="dog"/>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
Would be displayed like this:
-Pets
-Dogs
-Cats
How do I undentify the root node? I think that once I got that I can recurse into each type in the root elemet to find its name.
I am looking at this XSD specifically!. Should I start from the element called 'Document'? It contains the 2 top level elements in this type of file - 'GrpHdr' and 'OrgnlGrpInfAndSts'.
Is this is a standard way to tackle something like this?
Apparently there isn't since an XSD may contain more then 1 root element.

Categories