blob: eb5399098a250aa681fb93ed533ca18da14b4aa7 [file] [log] [blame]
package org.unicode.cldr.util;
import com.thaiopensource.relaxng.edit.SchemaCollection;
import com.thaiopensource.relaxng.input.InputFailedException;
import com.thaiopensource.relaxng.input.InputFormat;
import com.thaiopensource.relaxng.input.dtd.DtdInputFormat;
import com.thaiopensource.relaxng.output.LocalOutputDirectory;
import com.thaiopensource.relaxng.output.OutputFailedException;
import com.thaiopensource.relaxng.output.OutputFormat;
import com.thaiopensource.relaxng.output.xsd.XsdOutputFormat;
import com.thaiopensource.relaxng.translate.util.InvalidParamsException;
import com.thaiopensource.xml.sax.ErrorHandlerImpl;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/** Called by GenerateDtd to convert DTD to XSD */
public class DTD2XSD {
public static void write(DtdData data, DtdType type) {
final String dtdPath = CLDRPaths.BASE_DIRECTORY + type.dtdPath;
final String xsdPath = CLDRPaths.BASE_DIRECTORY + type.getXsdPath();
writeXsd(type, data, dtdPath, xsdPath);
System.err.println("Wrote XSD: " + xsdPath);
}
private static void writeXsd(
DtdType type, DtdData data, final String dtdPath, final String xsdPath) {
// Step 1: fire up Trang to do the basic conversion
InputFormat inFormat = new DtdInputFormat();
OutputFormat outputFormat = new XsdOutputFormat();
ErrorHandlerImpl eh = new ErrorHandlerImpl();
final String inputUri = new File(dtdPath).toURI().toString();
String params[] = {};
try {
SchemaCollection sc = inFormat.load(inputUri, params, "xsd", eh, null);
outputFormat.output(
sc,
new LocalOutputDirectory(inputUri, new File(xsdPath), ".xsd", "UTF-8", 72, 2),
params,
"dtd",
eh);
} catch (InputFailedException
| InvalidParamsException
| IOException
| SAXException
| OutputFailedException e) {
e.printStackTrace();
System.err.println("Error generating XSD from " + inputUri);
}
// Step 2: re-parse
final Document d = LDMLUtilities.parse(xsdPath, false, false);
// Step 3: remove all <!-- @ comments
removeAnnotationComments(null, d);
// Step 4: write .xsd out
try (OutputStream file =
new BufferedOutputStream(new FileOutputStream(xsdPath, false)); // Append
PrintWriter pw = new PrintWriter(file, false, StandardCharsets.UTF_8); ) {
LDMLUtilities.printDOMTree(
d,
pw,
null,
"<!--\n"
+ "Note: The .xsd files are a Technology Preview. They are subject to change or removal in future CLDR versions.\n"
+ "Note: DTD @-annotations are not currently converted to .xsd. For full CLDR file validation, use the DTD and CLDR tools.\n"
+ "-->\n\n" /* copyright is passthrough from .dtd */);
} catch (Throwable t) {
throw new RuntimeException("Generating .xsd for " + type, t);
}
}
static void removeAnnotationComments(Node parent, Node n) {
if (parent != null && n.getNodeType() == Node.COMMENT_NODE) {
if (n.getTextContent().trim().startsWith("@")) {
parent.removeChild(n);
}
} else {
NodeList nl = n.getChildNodes();
if (nl != null) {
// walk backwards because of deletion
for (int i = nl.getLength() - 1; i > 0; i--) {
// recurse
removeAnnotationComments(n, nl.item(i));
}
}
}
}
}