Nobody wants to hand-write serialisable C# classes for an XML Schema, and Mono's xsd generates them for you in one command. You will also learn to infer a schema from an XML document, and to choose an output directory deliberately rather than letting generated files land wherever. The examples target the xsd shipped by Ubuntu's mono-devel package.
Allow about fifteen minutes. You need a shell, a readable .xsd or .xml file, and permission to write the output directory. The examples write under /tmp; adapt the paths for a real project.
Checkpoint: This tool generates files. It does not validate an XML document against a schema, compile the generated source, or install anything. Keep those tasks separate when checking a build.
Start with the binary and package version. These are ordinary, read-only commands and do not need sudo:
$ command -v xsd
/usr/bin/xsd
$ dpkg-query -W -f='${Package} ${Version}\n' mono-devel
mono-devel 6.8.0.105+dfsg-3.6ubuntu2
$ xsd /help
xsd.exe - a utility for generating schema or class files
Your package revision may differ. The installed help calls the program xsd.exe, even though the executable on this system is xsd.
The manpage documents four input modes: an XSD with /classes, an XSD with /dataset, an assembly, or one or more XML instances. The help output is useful for this installed build because it also shows short forms such as /c, /d and /o.
For a repeatable test, create an XSD with one root element and two fields. This example describes a book. Save it as /tmp/xsd-guide/schema.xsd, or point the later commands at your own schema:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="book">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string" />
<xs:element name="pages" type="xs:positiveInteger" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Check that the input exists before generating anything:
$ test -r /tmp/xsd-guide/schema.xsd && echo 'schema is readable'
schema is readable
Create a new destination directory, then ask for C# output. /language:CS selects C#, and /outputdir keeps generated files out of the source directory:
$ mkdir -p /tmp/xsd-guide/classes
$ xsd /tmp/xsd-guide/schema.xsd /classes /language:CS \
/outputdir:/tmp/xsd-guide/classes
Written file /tmp/xsd-guide/classes/schema.cs
Inspect the result rather than assuming the name or namespace:
$ find /tmp/xsd-guide/classes -maxdepth 1 -type f -printf '%f\n'
schema.cs
$ sed -n '1,35p' /tmp/xsd-guide/classes/schema.cs
//------------------------------------------------------------------------------
// <auto-generated>
// ...
// namespace Schemas {
// ...
The generated source contains a serialisable class for book, with XML serialization attributes and properties for title and pages. The class is source code, not a compiled library. Compile it with the compiler and project settings appropriate to your application.
Checkpoint: If the output directory already contains a generated file with the same name, stop and inspect it before rerunning. Redirecting generation into a clean directory makes accidental replacement easier to spot. If you need a different namespace, the installed command accepts /namespace:NAME; verify the generated namespace afterwards.
Use /dataset when your consumer expects a typed DataSet rather than ordinary XML-serialisable classes:
$ xsd /tmp/xsd-guide/schema.xsd /dataset \
/outputdir:/tmp/xsd-guide/classes
Written file /tmp/xsd-guide/classes/schema.cs
This mode has a different generated model. Do not treat /classes and /dataset as interchangeable flags. Generate each into a separate directory if you need to compare them, because both modes can choose the same output filename.
Only select one of these generation modes for a single invocation. For example, combining an XML instance and an XSD produces the error Can only generate one of classes or datasets. Put the inputs into separate commands instead.
The XML-instance mode accepts one or more documents and writes an inferred schema. Create a small instance that matches the earlier example:
<?xml version="1.0" encoding="utf-8"?>
<book><title>Example</title><pages>12</pages></book>
Run the inference in another directory:
$ mkdir -p /tmp/xsd-guide/inferred
$ xsd /tmp/xsd-guide/sample.xml /outputdir:/tmp/xsd-guide/inferred
Written file /tmp/xsd-guide/inferred/sample.xsd
$ find /tmp/xsd-guide/inferred -maxdepth 1 -type f -printf '%f\n'
sample.xsd
Open the inferred file and review its assumptions:
$ sed -n '1,24p' /tmp/xsd-guide/inferred/sample.xsd
<?xml version="1.0" standalone="yes"?>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" ...>
<xs:element name="book">
...
</xs:element>
</xs:schema>
Inference is based on the documents you provide. In this installed version, the numeric-looking pages value in the sample was inferred as xs:string, so review types, optionality and repeated elements before treating the result as a contract. Add representative instances if the real data has multiple shapes.
/classes or /dataset. An XML instance needs no mode flag. An assembly uses its file name and can take /type:NAME./outputdir names a directory, not a complete output filename. Create it first and check the command's "Written file" line.CS and VB. Use the exact spelling and inspect the extension and source before compiling.mv /tmp/xsd-guide/classes/schema.cs /tmp/xsd-guide/classes/schema.cs.old. To undo that move, run mv /tmp/xsd-guide/classes/schema.cs.old /tmp/xsd-guide/classes/schema.cs after confirming the destination is safe.None of these examples needs elevated privileges. Use sudo only when your chosen input or destination is genuinely inaccessible, and prefer fixing ownership or choosing a user-writable build directory. Do not run generated source merely because xsd produced it: review and compile it under your normal project controls.
xsd resolves to the executable and its mono-devel version is noted.