From d2b0bdc5ced4dbdc23194b5c095acaba85339ef6 Mon Sep 17 00:00:00 2001 From: Jens Wille Date: Fri, 24 Sep 2021 20:04:05 +0200 Subject: [PATCH] Make MARC21 XML handler attribute marker configurable. Related to: #336, #379 --- metafacture-biblio/build.gradle | 7 ++++ .../biblio/marc21/MarcXmlHandler.java | 17 +++++++-- .../biblio/marc21/MarcXmlHandlerTest.java | 37 +++++++++++++++++++ 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/metafacture-biblio/build.gradle b/metafacture-biblio/build.gradle index 7faf64733..87bbff635 100644 --- a/metafacture-biblio/build.gradle +++ b/metafacture-biblio/build.gradle @@ -31,3 +31,10 @@ dependencies { testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:2.5.5' } + +test { + testLogging { + showStandardStreams = true + exceptionFormat = 'full' + } +} diff --git a/metafacture-biblio/src/main/java/org/metafacture/biblio/marc21/MarcXmlHandler.java b/metafacture-biblio/src/main/java/org/metafacture/biblio/marc21/MarcXmlHandler.java index 7de7fb1ef..37fa25fa9 100644 --- a/metafacture-biblio/src/main/java/org/metafacture/biblio/marc21/MarcXmlHandler.java +++ b/metafacture-biblio/src/main/java/org/metafacture/biblio/marc21/MarcXmlHandler.java @@ -38,6 +38,8 @@ @FluxCommand("handle-marcxml") public final class MarcXmlHandler extends DefaultXmlPipe { + public static final String DEFAULT_ATTRIBUTE_MARKER = ""; + private static final String SUBFIELD = "subfield"; private static final String DATAFIELD = "datafield"; private static final String CONTROLFIELD = "controlfield"; @@ -45,6 +47,8 @@ public final class MarcXmlHandler extends DefaultXmlPipe { private static final String NAMESPACE = "http://www.loc.gov/MARC21/slim"; private static final String LEADER = "leader"; private static final String TYPE = "type"; + + private String attributeMarker = DEFAULT_ATTRIBUTE_MARKER; private String currentTag = ""; private String namespace = NAMESPACE; private StringBuilder builder = new StringBuilder(); @@ -60,6 +64,14 @@ private boolean checkNamespace(final String uri) { return namespace == null || namespace.equals(uri); } + public void setAttributeMarker(final String attributeMarker) { + this.attributeMarker = attributeMarker; + } + + public String getAttributeMarker() { + return attributeMarker; + } + @Override public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) throws SAXException { if (SUBFIELD.equals(localName)) { @@ -75,7 +87,7 @@ else if (CONTROLFIELD.equals(localName)) { } else if (RECORD.equals(localName) && checkNamespace(uri)) { getReceiver().startRecord(""); - getReceiver().literal(TYPE, attributes.getValue(TYPE)); + getReceiver().literal(attributeMarker + TYPE, attributes.getValue(TYPE)); } else if (LEADER.equals(localName)) { builder = new StringBuilder(); @@ -87,18 +99,15 @@ else if (LEADER.equals(localName)) { public void endElement(final String uri, final String localName, final String qName) throws SAXException { if (SUBFIELD.equals(localName)) { getReceiver().literal(currentTag, builder.toString().trim()); - } else if (DATAFIELD.equals(localName)) { getReceiver().endEntity(); } else if (CONTROLFIELD.equals(localName)) { getReceiver().literal(currentTag, builder.toString().trim()); - } else if (RECORD.equals(localName) && checkNamespace(uri)) { getReceiver().endRecord(); - } else if (LEADER.equals(localName)) { getReceiver().literal(currentTag, builder.toString()); diff --git a/metafacture-biblio/src/test/java/org/metafacture/biblio/marc21/MarcXmlHandlerTest.java b/metafacture-biblio/src/test/java/org/metafacture/biblio/marc21/MarcXmlHandlerTest.java index 094b4547e..3902a6041 100644 --- a/metafacture-biblio/src/test/java/org/metafacture/biblio/marc21/MarcXmlHandlerTest.java +++ b/metafacture-biblio/src/test/java/org/metafacture/biblio/marc21/MarcXmlHandlerTest.java @@ -23,7 +23,9 @@ import org.junit.Before; import org.junit.Test; import org.metafacture.framework.StreamReceiver; +import org.mockito.InOrder; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; @@ -130,4 +132,39 @@ public void issue330ShouldOptionallyRecognizeRecordsWithoutNamespace() verifyNoMoreInteractions(receiver); } + @Test + public void shouldNotEncodeTypeAttributeAsMarkedLiteral() throws SAXException { + final AttributesImpl attributes = new AttributesImpl(); + attributes.addAttribute(NAMESPACE, "type", "type", "CDATA", "bibliographic"); + + marcXmlHandler.startElement(NAMESPACE, RECORD, "", attributes); + marcXmlHandler.endElement(NAMESPACE, RECORD, ""); + + final InOrder ordered = Mockito.inOrder(receiver); + ordered.verify(receiver).startRecord(""); + ordered.verify(receiver).literal(TYPE, "bibliographic"); + ordered.verify(receiver).endRecord(); + ordered.verifyNoMoreInteractions(); + verifyNoMoreInteractions(receiver); + } + + @Test + public void issue336_shouldEncodeTypeAttributeAsLiteralWithConfiguredMarker() throws SAXException { + final String marker = "~"; + marcXmlHandler.setAttributeMarker(marker); + + final AttributesImpl attributes = new AttributesImpl(); + attributes.addAttribute(NAMESPACE, "type", "type", "CDATA", "bibliographic"); + + marcXmlHandler.startElement(NAMESPACE, RECORD, "", attributes); + marcXmlHandler.endElement(NAMESPACE, RECORD, ""); + + final InOrder ordered = Mockito.inOrder(receiver); + ordered.verify(receiver).startRecord(""); + ordered.verify(receiver).literal(marker + TYPE, "bibliographic"); + ordered.verify(receiver).endRecord(); + ordered.verifyNoMoreInteractions(); + verifyNoMoreInteractions(receiver); + } + }