Skip to content

Commit ef67134

Browse files
authored
Merge pull request #4547 from evolvedbinary/feature/doctype-serialization
Enable Document Type Declaration Serialization
2 parents 6ebb1c1 + b973763 commit ef67134

File tree

28 files changed

+444
-80
lines changed

28 files changed

+444
-80
lines changed

exist-core/src/main/java/org/exist/client/InteractiveClient.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
import se.softhouse.jargo.ArgumentException;
8585

8686
import static java.nio.charset.StandardCharsets.UTF_8;
87+
import static org.exist.storage.serializers.EXistOutputKeys.OUTPUT_DOCTYPE;
8788

8889
/**
8990
* Command-line client based on the XML:DB API.
@@ -137,6 +138,7 @@ public class InteractiveClient {
137138
defaultProps.setProperty(USER, USER_DEFAULT);
138139
defaultProps.setProperty(EDITOR, EDIT_CMD);
139140
defaultProps.setProperty(INDENT, "true");
141+
defaultProps.setProperty(OUTPUT_DOCTYPE, "true");
140142
defaultProps.setProperty(ENCODING, ENCODING_DEFAULT.name());
141143
defaultProps.setProperty(COLORS, "false");
142144
defaultProps.setProperty(PERMISSIONS, "false");

exist-core/src/main/java/org/exist/http/RESTServer.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ private String getParameter(final HttpServletRequest request, final RESTServerPa
250250
*
251251
* <li>_xsl: an URI pointing to an XSL stylesheet that will be applied to
252252
* the returned XML.</li>
253+
*
254+
* <li>_output-doctype: if set to "yes", the returned XML will include
255+
* a Document Type Declaration if one is present, if "no" the Document Type Declaration will be omitted.</li>
253256
* </ul>
254257
*
255258
* @param broker the database broker
@@ -346,6 +349,14 @@ public void doGet(final DBBroker broker, final Txn transaction, final HttpServle
346349
if ((option = getParameter(request, Indent)) != null) {
347350
outputProperties.setProperty(OutputKeys.INDENT, option);
348351
}
352+
if ((option = getParameter(request, Output_Doctype)) != null) {
353+
// take user query-string specified output-doctype setting
354+
outputProperties.setProperty(EXistOutputKeys.OUTPUT_DOCTYPE, option);
355+
} else {
356+
// set output-doctype by configuration
357+
final String outputDocType = broker.getConfiguration().getProperty(Serializer.PROPERTY_OUTPUT_DOCTYPE, "yes");
358+
outputProperties.setProperty(EXistOutputKeys.OUTPUT_DOCTYPE, outputDocType);
359+
}
349360
if ((option = getParameter(request, Source)) != null && !safeMode) {
350361
source = "yes".equals(option);
351362
}

exist-core/src/main/java/org/exist/http/RESTServerParameter.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,18 @@ enum RESTServerParameter {
346346
* <exist:property name = string
347347
* value = string/>
348348
*/
349-
Property;
349+
Property,
350+
351+
/**
352+
* Can be used in the Query String of a GET request
353+
* to indicate that the doctype of an XML document should also
354+
* be serialized if present.
355+
*
356+
* Contexts: GET
357+
*
358+
* The value of the parameter should be either "yes" or "no".
359+
*/
360+
Output_Doctype;
350361

351362
/**
352363
* Get the parameter key that is
@@ -366,6 +377,6 @@ public String queryStringKey() {
366377
* @return The parameter key, suitable for use in an XML document
367378
*/
368379
public String xmlKey() {
369-
return name().toLowerCase();
380+
return name().toLowerCase().replace('_', '-');
370381
}
371382
}

exist-core/src/main/java/org/exist/protocolhandler/xmlrpc/XmlrpcDownload.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
3737

3838
import org.exist.protocolhandler.xmldb.XmldbURL;
39+
import org.exist.storage.serializers.EXistOutputKeys;
40+
41+
import javax.xml.transform.OutputKeys;
3942

4043
import static java.nio.charset.StandardCharsets.UTF_8;
4144

@@ -75,8 +78,9 @@ public void stream(final XmldbURL xmldbURL, final OutputStream os) throws IOExce
7578

7679
// Setup xml serializer
7780
final Map<String, String> options = new HashMap<>();
78-
options.put("indent", "no");
79-
options.put("encoding", UTF_8.name());
81+
options.put(OutputKeys.INDENT, "no");
82+
options.put(OutputKeys.ENCODING, UTF_8.name());
83+
options.put(EXistOutputKeys.OUTPUT_DOCTYPE, "yes"); // Preserve doctype
8084

8185
// Setup client parameters
8286
final List<Object> params = new ArrayList<>();

exist-core/src/main/java/org/exist/storage/serializers/Serializer.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ public abstract class Serializer implements XMLReader {
118118
protected final static Logger LOG = LogManager.getLogger(Serializer.class);
119119

120120
public static final String CONFIGURATION_ELEMENT_NAME = "serializer";
121+
public static final String OUTPUT_DOCTYPE_ATTRIBUTE = "output-doctype";
122+
public static final String PROPERTY_OUTPUT_DOCTYPE = "serialization.output-doctype";
121123
public static final String ENABLE_XINCLUDE_ATTRIBUTE = "enable-xinclude";
122124
public static final String PROPERTY_ENABLE_XINCLUDE = "serialization.enable-xinclude";
123125
public static final String ENABLE_XSL_ATTRIBUTE = "enable-xsl";

exist-core/src/main/java/org/exist/util/Configuration.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,12 @@ private void configureHtmlToXmlParser(final Element parser) {
652652
*/
653653
private void configureSerializer( Element serializer )
654654
{
655+
final String outputDocType = getConfigAttributeValue( serializer, Serializer.OUTPUT_DOCTYPE_ATTRIBUTE );
656+
if (outputDocType != null) {
657+
config.put(Serializer.PROPERTY_OUTPUT_DOCTYPE, outputDocType);
658+
LOG.debug(Serializer.PROPERTY_OUTPUT_DOCTYPE + ": {}", config.get(Serializer.PROPERTY_OUTPUT_DOCTYPE));
659+
}
660+
655661
final String xinclude = getConfigAttributeValue( serializer, Serializer.ENABLE_XINCLUDE_ATTRIBUTE );
656662

657663
if( xinclude != null ) {

exist-core/src/main/java/org/exist/xmldb/LocalCollection.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public class LocalCollection extends AbstractLocal implements EXistCollection {
8989
defaultProperties.setProperty(EXistOutputKeys.EXPAND_XINCLUDES, "yes");
9090
defaultProperties.setProperty(EXistOutputKeys.PROCESS_XSL_PI, "no");
9191
defaultProperties.setProperty(NORMALIZE_HTML, "no");
92+
defaultProperties.setProperty(EXistOutputKeys.OUTPUT_DOCTYPE, "yes");
9293
}
9394

9495
private final XmldbURI path;

exist-core/src/main/java/org/exist/xmlrpc/RpcConnection.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,11 @@ private String getDocumentAsString(final XmldbURI docUri, final Map<String, Obje
663663
}
664664

665665
private void serialize(final DBBroker broker, final Properties properties, final ConsumerE<Serializer, SAXException> toSaxFunction, final Writer writer) throws SAXException, IOException {
666+
if (!properties.containsKey(EXistOutputKeys.OUTPUT_DOCTYPE)) {
667+
final String outputDocType = broker.getConfiguration().getProperty(Serializer.PROPERTY_OUTPUT_DOCTYPE, "yes");
668+
properties.setProperty(EXistOutputKeys.OUTPUT_DOCTYPE, outputDocType);
669+
}
670+
666671
final Serializer serializer = broker.borrowSerializer();
667672

668673
SAXSerializer saxSerializer = null;

exist-core/src/main/java/org/exist/xquery/functions/fn/FunSerialize.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,14 @@ private static boolean isSerializationParametersElement(final Item item) {
131131
* <a href="http://www.w3.org/TR/xslt-xquery-serialization-30/#serdm">XSLT and XQuery Serialization 3.0 - Sequence Normalization</a>.
132132
*
133133
* @param callingExpr the expression from which the function is called.
134-
* needed for error reporting
135-
* @param context current context
136-
* @param input non-normalized sequence
137-
* @param itemSeparator placed between each item
138-
* @return normalized sequence
139-
* @throws XPathException in case of dynamic error
134+
* Needed for error reporting
135+
* @param context current context.
136+
* @param input non-normalized sequence.
137+
* @param itemSeparator the item separator placed between each item.
138+
*
139+
* @return normalized sequence.
140+
*
141+
* @throws XPathException in case of dynamic error.
140142
*/
141143
public static Sequence normalize(final Expression callingExpr, final XQueryContext context, final Sequence input, final String itemSeparator) throws XPathException {
142144
if (input.isEmpty())

exist-core/src/main/java/org/exist/xquery/util/SerializerUtils.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,16 +185,18 @@ public Sequence getDefaultValue() {
185185
* for Exist xquery specific functions
186186
*/
187187
public enum ExistParameterConvention implements ParameterConvention<QName> {
188-
EXPAND_XINCLUDE("expand-xincludes", Type.BOOLEAN, Cardinality.ZERO_OR_ONE, BooleanValue.TRUE),
189-
PROCESS_XSL_PI("process-xsl-pi", Type.BOOLEAN, Cardinality.ZERO_OR_ONE, BooleanValue.TRUE),
190-
JSON_IGNORE_WHITE_SPACE_TEXT_NODES("json-ignore-whitespace-text-nodes", Type.BOOLEAN, Cardinality.ZERO_OR_ONE, BooleanValue.TRUE),
191-
HIGHLIGHT_MATCHES("highlight-matches", Type.STRING, Cardinality.ZERO_OR_ONE, new StringValue("none")),
192-
JSONP("jsonp", Type.STRING, Cardinality.ZERO_OR_ONE, Sequence.EMPTY_SEQUENCE),
193-
ADD_EXIST_ID("add-exist-id", Type.STRING, Cardinality.ZERO_OR_ONE, new StringValue("none")),
188+
OUTPUT_DOCTYPE(EXistOutputKeys.OUTPUT_DOCTYPE, Type.BOOLEAN, Cardinality.ZERO_OR_ONE, BooleanValue.FALSE),
189+
EXPAND_XINCLUDE(EXistOutputKeys.EXPAND_XINCLUDES, Type.BOOLEAN, Cardinality.ZERO_OR_ONE, BooleanValue.TRUE),
190+
PROCESS_XSL_PI(EXistOutputKeys.PROCESS_XSL_PI, Type.BOOLEAN, Cardinality.ZERO_OR_ONE, BooleanValue.TRUE),
191+
JSON_IGNORE_WHITE_SPACE_TEXT_NODES(EXistOutputKeys.JSON_IGNORE_WHITESPACE_TEXT_NODES, Type.BOOLEAN, Cardinality.ZERO_OR_ONE, BooleanValue.TRUE),
192+
HIGHLIGHT_MATCHES(EXistOutputKeys.HIGHLIGHT_MATCHES, Type.STRING, Cardinality.ZERO_OR_ONE, new StringValue("none")),
193+
JSONP(EXistOutputKeys.JSONP, Type.STRING, Cardinality.ZERO_OR_ONE, Sequence.EMPTY_SEQUENCE),
194+
ADD_EXIST_ID(EXistOutputKeys.ADD_EXIST_ID, Type.STRING, Cardinality.ZERO_OR_ONE, new StringValue("none")),
194195
// default of 4 corresponds to the existing eXist default, although 3 is in the spec
195196
INDENT_SPACES("indent-spaces", Type.INTEGER, Cardinality.ZERO_OR_ONE, new IntegerValue(4)),
196197
INSERT_FINAL_NEWLINE(EXistOutputKeys.INSERT_FINAL_NEWLINE, Type.BOOLEAN, Cardinality.ZERO_OR_ONE, BooleanValue.FALSE);
197198

199+
198200
private final QName parameterName;
199201
private final int type;
200202
private final Cardinality cardinality;

0 commit comments

Comments
 (0)