diff --git a/metafacture-xml/src/main/java/org/metafacture/xml/SimpleXmlEncoder.java b/metafacture-xml/src/main/java/org/metafacture/xml/SimpleXmlEncoder.java index 13b4d7fc9..485ed7c62 100644 --- a/metafacture-xml/src/main/java/org/metafacture/xml/SimpleXmlEncoder.java +++ b/metafacture-xml/src/main/java/org/metafacture/xml/SimpleXmlEncoder.java @@ -29,6 +29,7 @@ import org.metafacture.framework.helpers.DefaultXmlPipe; import java.io.IOException; +import java.io.StringReader; import java.net.URL; import java.util.ArrayList; import java.util.Collections; @@ -68,6 +69,7 @@ public final class SimpleXmlEncoder extends DefaultStreamPipe\n"; private static final String XMLNS_MARKER = " xmlns"; + private static final String DEFAULT = "__default"; private final StringBuilder builder = new StringBuilder(); @@ -141,9 +143,7 @@ public void setNamespaceFile(final String file) { catch (final IOException e) { throw new MetafactureException("Failed to load namespaces list", e); } - for (final Entry entry : properties.entrySet()) { - namespaces.put(entry.getKey().toString(), entry.getValue().toString()); - } + propertiesToMap(properties); } /** @@ -159,9 +159,7 @@ public void setNamespaceFile(final URL url) { catch (final IOException e) { throw new MetafactureException("Failed to load namespaces list", e); } - for (final Entry entry : properties.entrySet()) { - namespaces.put(entry.getKey().toString(), entry.getValue().toString()); - } + propertiesToMap(properties); } /** @@ -218,6 +216,25 @@ public void setNamespaces(final Map namespaces) { this.namespaces = namespaces; } + /** + * Sets the namespace(s). + * + * @param namespacesString the namespaces as a String. It allows Java Properties + * structure, i.e. a key-value structure where the key is separated from the value + * by an equal sign '=', a colon ':' or a white space ' '. Multiple namespaces + * are separated by a line feed '\n' + */ + public void setNamespaces(final String namespacesString) { + final Properties properties = new Properties(); + try (StringReader sr = new StringReader(namespacesString)) { + properties.load(sr); + } + catch (final IOException e) { + throw new MetafactureException("Failed to create namespace list"); + } + propertiesToMap(properties); + } + /** * Sets the attribute marker. * @@ -256,7 +273,7 @@ else if (atStreamStart) { private void addNamespacesToElement() { for (final Entry namespace : namespaces.entrySet()) { final String key = namespace.getKey(); - final String name = XMLNS_MARKER + (key.isEmpty() ? "" : ":") + key; + final String name = XMLNS_MARKER + (isDefaultNamespace(key) ? "" : ":" + key); element.addAttribute(name, namespace.getValue()); } } @@ -326,7 +343,7 @@ private void writeHeader() { builder.append(rootTag); for (final Entry entry : namespaces.entrySet()) { builder.append(XMLNS_MARKER); - if (!entry.getKey().isEmpty()) { + if (!isDefaultNamespace(entry.getKey())) { builder.append(':'); builder.append(entry.getKey()); } @@ -351,6 +368,14 @@ protected static void writeEscaped(final StringBuilder builder, final String str builder.append(XmlUtil.escape(str, false)); } + private boolean isDefaultNamespace(final String ns) { + return ns.isEmpty() || ns.equals(DEFAULT); + } + + private void propertiesToMap(final Properties properties) { + properties.forEach((k, v) -> namespaces.put(k.toString(), v.toString())); + } + /** * An XML element. * diff --git a/metafacture-xml/src/test/java/org/metafacture/xml/SimpleXmlEncoderTest.java b/metafacture-xml/src/test/java/org/metafacture/xml/SimpleXmlEncoderTest.java index d4b2c6197..580a1ff5b 100644 --- a/metafacture-xml/src/test/java/org/metafacture/xml/SimpleXmlEncoderTest.java +++ b/metafacture-xml/src/test/java/org/metafacture/xml/SimpleXmlEncoderTest.java @@ -112,6 +112,15 @@ public void shouldAddNamespaceToRootElement() { getResultXml()); } + @Test + public void shouldAddMultipleNamespacesFromParameterToRootElement() { + simpleXmlEncoder.setNamespaces("__default=http://default.org/ns\nns=http://example.org/ns\nns1=http://example.org/ns1"); + + emitEmptyRecord(); + + assertEquals("", + getResultXml()); + } @Test public void shouldAddNamespaceWithEmptyKeyAsDefaultNamespaceToRootTag() { final Map namespaces = new HashMap(); @@ -124,6 +133,18 @@ public void shouldAddNamespaceWithEmptyKeyAsDefaultNamespaceToRootTag() { getResultXml()); } + @Test + public void shouldAddNamespaceWithDefaultKeyAsDefaultNamespaceToRootTag() { + final Map namespaces = new HashMap(); + namespaces.put("__default", "http://example.org/ns"); + simpleXmlEncoder.setNamespaces(namespaces); + + emitEmptyRecord(); + + assertEquals("", + getResultXml()); + } + @Test public void shouldAddNamespaceWithEmptyKeyFromPropertiesFileAsDefaultNamespaceToRootTag() { simpleXmlEncoder.setNamespaceFile("org/metafacture/xml/SimpleXmlEncoderTest_namespaces.properties"); @@ -170,6 +191,19 @@ public void shouldAddNamespaceWithEmptyKeyAsDefaultNamespaceToRecordTag() { getResultXml()); } + @Test + public void shouldAddNamespaceWithDefaultKeyAsDefaultNamespaceToRecordTag() { + final Map namespaces = new HashMap(); + namespaces.put("__default", "http://example.org/ns"); + simpleXmlEncoder.setNamespaces(namespaces); + simpleXmlEncoder.setWriteRootTag(false); + + emitEmptyRecord(); + + assertEquals("", + getResultXml()); + } + @Test public void shouldAddNamespaceWithEmptyKeyFromPropertiesFileAsDefaultNamespaceToRecordTag() { simpleXmlEncoder.setNamespaceFile("org/metafacture/xml/SimpleXmlEncoderTest_namespaces.properties"); @@ -180,6 +214,16 @@ public void shouldAddNamespaceWithEmptyKeyFromPropertiesFileAsDefaultNamespaceTo assertEquals("", getResultXml()); } + @Test + public void shouldAddNamespaceWithEmptyKeyFromParameterAsDefaultNamespaceToRecordTag() { + simpleXmlEncoder.setNamespaces("=http://example.org/ns"); + simpleXmlEncoder.setWriteRootTag(false); + + emitEmptyRecord(); + + assertEquals("", + getResultXml()); + } @Test public void testShouldEncodeUnnamedLiteralsAsText() {