DocumentInfo dtdRoot = (DocumentInfo)builder.getCurrentRoot();
SequenceIterator children = dtdRoot.iterateAxis(Axis.CHILD);
NodeInfo docType = (NodeInfo)children.next();
if (docType == null || !("doctype".equals(docType.getLocalPart()))) {
XPathException e = new XPathException("saxon:doctype instruction must contain dtd:doctype");
e.setXPathContext(context);
throw e;
}
String name = Navigator.getAttributeValue(docType, "", "name");
String system = Navigator.getAttributeValue(docType, "", "system");
String publicid = Navigator.getAttributeValue(docType, "", "public");
if (name == null) {
XPathException e = new XPathException("dtd:doctype must have a name attribute");
e.setXPathContext(context);
throw e;
}
write(out, "<!DOCTYPE " + name + ' ');
if (system != null) {
if (publicid != null) {
write(out, "PUBLIC \"" + publicid + "\" \"" + system + '\"');
} else {
write(out, "SYSTEM \"" + system + '\"');
}
}
boolean openSquare = false;
children = docType.iterateAxis(Axis.CHILD);
NodeInfo child = (NodeInfo)children.next();
if (child != null) {
write(out, " [");
openSquare = true;
}
while (child != null) {
String localname = child.getLocalPart();
if ("element".equals(localname)) {
String elname = Navigator.getAttributeValue(child, "", "name");
String content = Navigator.getAttributeValue(child, "", "content");
if (elname == null) {
XPathException e = new XPathException("dtd:element must have a name attribute");
e.setXPathContext(context);
throw e;
}
if (content == null) {
XPathException e = new XPathException("dtd:element must have a content attribute");
e.setXPathContext(context);
throw e;
}
write(out, "\n <!ELEMENT " + elname + ' ' + content + '>');
} else if (localname.equals("attlist")) {
String elname = Navigator.getAttributeValue(child, "", "element");
if (elname == null) {
XPathException e = new XPathException("dtd:attlist must have an attribute named 'element'");
e.setXPathContext(context);
throw e;
}
write(out, "\n <!ATTLIST " + elname + ' ');
SequenceIterator attributes = child.iterateAxis(Axis.CHILD);
while (true) {
NodeInfo attDef = (NodeInfo)attributes.next();
if (attDef == null) {
break;
}
if ("attribute".equals(attDef.getLocalPart())) {
String atname = Navigator.getAttributeValue(attDef, "", "name");
String type = Navigator.getAttributeValue(attDef, "", "type");
String value = Navigator.getAttributeValue(attDef, "", "value");
if (atname == null) {
XPathException e = new XPathException("dtd:attribute must have a name attribute");
e.setXPathContext(context);
throw e;
}
if (type == null) {
XPathException e = new XPathException("dtd:attribute must have a type attribute");
e.setXPathContext(context);
throw e;
}
if (value == null) {
XPathException e = new XPathException("dtd:attribute must have a value attribute");
e.setXPathContext(context);
throw e;
}
write(out, "\n " + atname + ' ' + type + ' ' + value);
} else {
XPathException e = new XPathException("Unrecognized element within dtd:attlist");
e.setXPathContext(context);
throw e;
}
}
write(out, ">");
} else if (localname.equals("entity")) {
String entname = Navigator.getAttributeValue(child, "", "name");
String parameter = Navigator.getAttributeValue(child, "", "parameter");
String esystem = Navigator.getAttributeValue(child, "", "system");
String epublicid = Navigator.getAttributeValue(child, "", "public");
String notation = Navigator.getAttributeValue(child, "", "notation");
if (entname == null) {
XPathException e = new XPathException("dtd:entity must have a name attribute");
e.setXPathContext(context);
throw e;
}
// we could do a lot more checking now...
write(out, "\n <!ENTITY ");
if ("yes".equals(parameter)) {
write(out, "% ");
}
write(out, entname + ' ');
if (esystem != null) {
if (epublicid != null) {
write(out, "PUBLIC \"" + epublicid + "\" \"" + esystem + "\" ");
} else {
write(out, "SYSTEM \"" + esystem + "\" ");
}
}
if (notation != null) {
write(out, "NDATA " + notation + ' ');
}
SequenceIterator contents = child.iterateAxis(Axis.CHILD);
while (true) {
NodeInfo content = (NodeInfo)contents.next();
if (content == null) {
break;
}
content.copy(out, NodeInfo.NO_NAMESPACES, false, locationId);
}
write(out, ">");
} else if (localname.equals("notation")) {
String notname = Navigator.getAttributeValue(child, "", "name");
String nsystem = Navigator.getAttributeValue(child, "", "system");
String npublicid = Navigator.getAttributeValue(child, "", "public");
if (notname == null) {
XPathException e = new XPathException("dtd:notation must have a name attribute");
e.setXPathContext(context);
throw e;
}
if ((nsystem == null) && (npublicid == null)) {
XPathException e = new XPathException("dtd:notation must have a system attribute or a public attribute");
e.setXPathContext(context);
throw e;
}
write(out, "\n <!NOTATION " + notname);
if (npublicid != null) {
write(out, " PUBLIC \"" + npublicid + "\" ");
if (nsystem != null) {
write(out, '\"' + nsystem + "\" ");
}
} else {
write(out, " SYSTEM \"" + nsystem + "\" ");
}
write(out, ">");
} else {
XPathException e = new XPathException("Unrecognized element " + localname + " in DTD output");
e.setXPathContext(context);
throw e;
}
child = (NodeInfo)children.next();
}