Mono's mono-xmltool validates XML against a schema, transforms it with XSLT and pretty-prints it, all from one binary. You will finish with three repeatable commands: validate an instance against an XSD, transform a document with XSLT, and produce readable indentation without touching the source. The examples use the installed Mono package, version 6.8.0.105+dfsg-3.6ubuntu2.
Allow about fifteen minutes. You need a shell, mono-devel, an XML document, and the relevant schema or stylesheet. The examples write only to /tmp or standard output. They do not require sudo.
Check the binary and package before relying on option details. These are ordinary read-only commands:
$ command -v mono-xmltool
/usr/bin/mono-xmltool
$ dpkg-query -W -f='${Package} ${Version}\n' mono-devel
mono-devel 6.8.0.105+dfsg-3.6ubuntu2
$ mono-xmltool --help
Usage: mono-xmltool [options]
The installed help lists the four schema-specific validation switches, transformation, pretty printing, and a few options not described by this older manpage. This guide sticks to the documented XSD, XSLT and pretty-print workflows. Keep the help output with a script review if you are moving between Mono releases.
Checkpoint: You should have a working mono-xmltool path and a version number. If the command is missing, stop here and install or repair the package through your normal distribution process. Do not use an unverified binary copied into the working directory.
--validate-xsd takes the schema first and one or more XML instances after it. Create or select an XSD whose root element and child rules match the documents you intend to check. For a harmless test, use this small schema:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="message">
<xs:complexType>
<xs:sequence>
<xs:element name="text" type="xs:string"/>
</xs:sequence>
<xs:attribute name="id" type="xs:positiveInteger" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
With that schema in schema.xsd, this instance satisfies the required root, child and attribute:
$ mono-xmltool --validate-xsd schema.xsd valid.xml
$ printf 'exit status: %s\n' "$?"
exit status: 0
A successful run is quiet in this test. You can also use the generic --validate form when the schema extension identifies the validator:
$ mono-xmltool --validate schema.xsd valid.xml
Use the explicit switch when a script should make the expected schema language obvious. The manpage documents --validate-rng, --validate-rnc, --validate-nvdl and --validate-xsd; each requires its own grammar format.
Test the failure path before adding this command to a build or deployment check. This instance has <wrong> where the XSD requires <text>:
$ mono-xmltool --validate-xsd schema.xsd invalid.xml
The element 'message' has invalid child element 'wrong'. List of possible elements expected: 'text'.
$ printf 'exit status: %s\n' "$?"
exit status: 0
That output and status are from the installed Mono 6.8 build. In this test, the validator printed the schema error but still returned status 0. Do not write a wrapper that treats status 0 alone as proof that every instance is valid. Capture and inspect the command output, and test the exact failure behaviour again after changing Mono versions.
For a reviewable diagnostic log, capture both output streams without changing the source files:
$ mono-xmltool --validate-xsd schema.xsd invalid.xml > validation.log 2>&1
$ sed -n '1,20p' validation.log
The element 'message' has invalid child element 'wrong'. List of possible elements expected: 'text'.
There is no need for elevated privileges unless your input files are unreadable by your account. Fix the XML or schema, then rerun the same command. Validation does not repair either file.
--transform takes a stylesheet followed by the instance XML. The manpage says transformed output goes to standard output. The installed help also accepts an optional output path, which is useful when the result needs to become a file:
$ mono-xmltool --transform transform.xsl input.xml
<result>Hello XML</result>$ mono-xmltool --transform transform.xsl input.xml result.xml
$ sed -n '1,10p' result.xml
<result>Hello XML</result>
The first command writes its result directly into your terminal, so the next shell prompt may appear on the same line when the stylesheet does not emit a trailing newline. Use redirection or the optional output argument when another tool will consume the result:
$ mono-xmltool --transform transform.xsl input.xml > result.xml
$ test -s result.xml && echo 'transform produced a non-empty result'
transform produced a non-empty result
Warning: Shell redirection truncates an existing destination before mono-xmltool starts. Use a new name such as result.xml.new, inspect it, then replace an existing result only as a deliberate operation:
$ mono-xmltool --transform transform.xsl input.xml > result.xml.new
$ test -s result.xml.new && mv result.xml.new result.xml
If the transform fails, leave the old result in place and remove the incomplete temporary file after checking it. The mv above is the state-changing step; it does not need sudo when the directory is yours.
--prettyprint reads a named source and writes formatted XML to standard output. If the source is omitted, it reads standard input. If the result is omitted, output remains on standard output:
$ mono-xmltool --prettyprint input.xml
<?xml version="1.0"?>
<message id="7">
<text>Hello XML</text>
</message>
$ mono-xmltool --prettyprint < input.xml
<?xml version="1.0"?>
<message id="7">
<text>Hello XML</text>
</message>
To save a formatted copy, provide the result path as the second positional argument:
$ mono-xmltool --prettyprint input.xml pretty.xml
$ sed -n '1,10p' pretty.xml
<?xml version="1.0"?>
<message id="7">
<text>Hello XML</text>
</message>
Do not use the source path as the result path in a blind command. A failed or interrupted write can destroy the only copy. Write a new file, compare it with the original using diff -u, and replace the original only after you have a backup or version control:
$ cp --preserve=all input.xml input.xml.bak
$ mono-xmltool --prettyprint input.xml input.xml.new
$ diff -u input.xml input.xml.new
$ mv input.xml.new input.xml
To undo that deliberate replacement, restore the backup with mv input.xml.bak input.xml. That also changes state, so check the two paths before running it.
A message such as Could not find file normally means a path or permissions problem, not that the XML is invalid. Check the paths without changing anything:
$ test -r schema.xsd && echo 'schema readable'
schema readable
$ test -r input.xml && echo 'instance readable'
instance readable
$ command -v mono-xmltool
Keep the argument order visible in scripts: validator switch, schema, instance; transform switch, stylesheet, instance, optional result; pretty-print switch, optional source, optional result. Quote paths containing spaces. If a stylesheet imports other files, test from the directory and account for those dependencies before moving the command into a service.
Remember that pretty printing changes layout, not the document's meaning. It is not schema validation. A transformation can also produce well-formed XML that is unsuitable for the next system, so inspect the result and validate it separately when the output has a schema.