Test dtd2xsd Safely Before Trusting Its XSD Output

On the installed Mono 6.8.0.105 package, dtd2xsd prints an object-reference error and still exits 0, so trusting its return code alone will fool you. This guide shows how to test the small dtd2xsd utility supplied by mono-devel: create an XML document with a DTD, run the tool in its two documented modes, and check whether an XSD was really produced.

Allow about 10 minutes. You need a shell, the dtd2xsd executable, and permission to create files in a scratch directory. Nothing in this workflow needs root. Do not use a valuable output path until the command has succeeded with a disposable fixture.

1. Check the installed command

Confirm which executable will run and record the Debian package version. This avoids debugging a different Mono installation from the one described by the local manual page.

$ command -v dtd2xsd
/usr/bin/dtd2xsd
$ dpkg-query -W -f='${Package} ${Version}\n' mono-devel
mono-devel 6.8.0.105+dfsg-3.6ubuntu2

The manual page documents the command as dtd2xsd [options] instance-xmlfile optional-xsdfile. It says the instance document must reference or contain a DTD. It does not document any options, so treat the two positional forms as the useful interface.

2. Create a disposable DTD and XML instance

Use an external DTD first. The XML declaration and document type declaration make the input unambiguous, while the simple element keeps any conversion issue separate from application data.

$ mkdir -p /tmp/dtd2xsd-check
$ cd /tmp/dtd2xsd-check
$ cat > greeting.dtd <<'EOF'
<!ELEMENT greeting (#PCDATA)>
EOF
$ cat > greeting.xml <<'EOF'
<?xml version="1.0"?>
<!DOCTYPE greeting SYSTEM "/tmp/dtd2xsd-check/greeting.dtd">
<greeting>Hello</greeting>
EOF
$ xmllint --noout greeting.xml

If xmllint is not installed, inspect the two files directly and confirm that the absolute DTD path matches the file you created. Installing another package is outside this test and is not required by dtd2xsd.

Checkpoint: You have one XML instance and one DTD in /tmp/dtd2xsd-check. The XML is the input to dtd2xsd; pass the DTD itself only through the document type declaration.

3. Try schema output on standard output

With one argument, the manual page says the generated schema goes to the console. Capture both streams so an error cannot be mistaken for an XSD.

$ dtd2xsd greeting.xml > generated.xsd 2> dtd2xsd.err
$ status=$?
$ printf 'exit status: %s\n' "$status"
exit status: 0
$ sed -n '1,20p' dtd2xsd.err
ERROR: Object reference not set to an instance of an object
$ test -s generated.xsd && echo 'XSD output exists' || echo 'No XSD output'
No XSD output

That is the observed result with the package version in step 1. The zero exit status is not proof of success. A successful-looking shell prompt is also not proof: check the file size and the captured diagnostic.

4. Try the optional output-file argument

The second positional argument requests a file instead of standard output. Choose a new scratch filename. If you point this at an existing file, the program may replace it; preserve important files first and do not rely on an automatic backup.

$ dtd2xsd greeting.xml generated-file.xsd > output-mode.out 2> output-mode.err
$ status=$?
$ printf 'exit status: %s\n' "$status"
exit status: 0
$ cat output-mode.out
ERROR: Object reference not set to an instance of an object
$ test -s generated-file.xsd && echo 'XSD output exists' || echo 'No XSD output'
No XSD output

On this installation the diagnostic is printed even when an output filename is supplied, and no schema file appears. Do not feed a missing or empty result to a build, validator, or service as if it were a generated schema.

5. Decide whether to proceed

For a different host or a rebuilt Mono package, repeat the same checks. Treat the result as usable only when the command produces a non-empty file or valid console output, and the output parses as XML. A simple check for a file is:

$ test -s generated-file.xsd && xmllint --noout generated-file.xsd

Both commands must succeed. If your environment has no xmllint, use another XML parser already approved for that system, or inspect the output carefully before using it. The man page describes DTD conversion from an XML instance, not a general standalone DTD importer, and it does not promise a particular XSD shape or compatibility level.

Common distractions are passing greeting.dtd directly, assuming an empty output file is valid, and checking only $?. Keep the XML instance as the argument, keep the DTD declaration inside that instance, and verify the generated bytes. If you tested against a real destination and it was changed, restore it from your normal backup or version control; the tool has no documented undo operation.

Done means