



This macro started as a simple run command for validating DITA files:
xmllint --noout --dtdvalid /tmp/DITA-OT1.3/dtd/ditabase.dtd %f
Unfortunately, not all DITA documents reference the 'ditabase' DTD, so the command wasn't flexible enough. The following macro parses the current document for the DTD file specified in the DOCTYPE declaration. The advantage of this is that the macro now works for many different types of XML files.
// As necessary, edit lintCommand to specify the full path to xmllint
// Komodo on Windows has a bundled xmllint.exe in:
// \lib\support\xslt
var lintCommand = 'xmllint --noout --dtdvalid ';
var myView = ko.views.manager.currentView;
var headEnd = Math.min(myView.scimoz.length, 500);
var fileHead = myView.scimoz.getTextRange(0, headEnd);
var doctypeRe = new RegExp ('()', 'm');
var doctypeArray = doctypeRe.exec(fileHead);
var dtdRe = new RegExp ('^.*"(.*\.dtd)">$', 'm');
var dtdArray = dtdRe.exec(doctypeArray[1]);
if (!doctypeArray) {
alert("No DOCTYPE declaration found.");
}
else if (!dtdArray) {
alert("No DTD found in DOCTYPE declaration.");
}
else if (dtdArray[1]) {
var dtdFile = dtdArray[1];
checkSaved();
}
else {
alert("Error parsing file for DOCTYPE declaration.");
}
function checkSaved() {
if (myView.document.isUntitled) {
var answer = ko.dialogs.okCancel("File has not yet been saved. Would you like to save it now?", "OK");
if (answer == "OK") {
ko.commands.doCommand('cmd_save');
validate();
}
else {
return;
}
}
else if (myView.document.isDirty) {
var answer = ko.dialogs.okCancel("Changes have not yet been saved. Would you like to save now?", "OK");
if (answer == "OK") {
ko.commands.doCommand('cmd_save');
validate();
}
else {
return;
}
}
else {
validate();
}
}
function validate() {
try {
ko.run.runEncodedCommand(window, lintCommand + dtdFile +
' %f {"parseRegex": u"^(?P.+?):(?P\\\\d+):(?P.*)$", \
"showParsedOutputList": True, "cwd": u"%D", "parseOutput": True}');
} catch (e) {alert(e);}
}
// Komodo Macro for validating XML files using xmllint
// As necessary, edit lintCommand to specify the full path to xmllint
// Komodo on Windows has a bundled xmllint.exe in:
// \lib\support\xslt
var lintCommand = 'xmllint --noout --dtdvalid ';
var myView = ko.views.manager.currentView;
var headEnd = Math.min(myView.scimoz.length, 500);
var fileHead = myView.scimoz.getTextRange(0, headEnd);
var doctypeRe = new RegExp ('()', 'm');
var doctypeArray = doctypeRe.exec(fileHead);
var dtdRe = new RegExp ('^.*"(.*\.dtd)">$', 'm');
var dtdArray = dtdRe.exec(doctypeArray[1]);
if (!doctypeArray) {
alert("No DOCTYPE declaration found.");
}
else if (!dtdArray) {
alert("No DTD found in DOCTYPE declaration.");
}
else if (dtdArray[1]) {
var dtdFile = dtdArray[1];
checkSaved();
}
else {
alert("Error parsing file for DOCTYPE declaration.");
}
function checkSaved() {
if (myView.document.isUntitled) {
var answer = ko.dialogs.okCancel("File has not yet been saved. Would you like to save it now?", "OK");
if (answer == "OK") {
ko.commands.doCommand('cmd_save');
validate();
}
else {
return;
}
}
else if (myView.document.isDirty) {
var answer = ko.dialogs.okCancel("Changes have not yet been saved. Would you like to save now?", "OK");
if (answer == "OK") {
ko.commands.doCommand('cmd_save');
validate();
}
else {
return;
}
}
else {
validate();
}
}
function validate() {
try {
ko.run.runEncodedCommand(window, lintCommand + dtdFile +
' %f {"parseRegex": u"^(?P.+?):(?P\\\\d+):(?P.*)$", \
"showParsedOutputList": True, "cwd": u"%D", "parseOutput": True}');
} catch (e) {alert(e);}
}The macro won't work with all XML files. The document needs to have a DOCTYPE declaration with a DTD specified, and that DTD needs to be accessible (i.e. have a relative path from the current directory, or a public URL).
The command output is sent to the bottom pane and displayed in list format. When you double-click on an error or warning, Komodo jumps to and highlights the appropriate line in the editor tab.