Skip to content

Commit 27ba247

Browse files
committed
Merge branch 'master' of https://github.com/metafacture/metafacture-core into fixJavadoc
2 parents e568830 + 533b5c3 commit 27ba247

File tree

2 files changed

+75
-22
lines changed

2 files changed

+75
-22
lines changed

metafacture-biblio/src/main/java/org/metafacture/biblio/marc21/MarcXmlEncoder.java

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
import org.metafacture.framework.annotations.Out;
2626
import org.metafacture.framework.helpers.DefaultStreamPipe;
2727

28+
import java.util.Arrays;
2829
import java.util.Collections;
30+
import java.util.function.Function;
2931

3032
/**
3133
* Encodes a stream into MARCXML.
@@ -48,25 +50,48 @@ public final class MarcXmlEncoder extends DefaultStreamPipe<ObjectReceiver<Strin
4850
private static final String ROOT_OPEN = "<marc:collection xmlns:marc=\"http://www.loc.gov/MARC21/slim\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd\">";
4951
private static final String ROOT_CLOSE = "</marc:collection>";
5052

51-
private static final String RECORD_OPEN = "<marc:record>";
52-
private static final String RECORD_CLOSE = "</marc:record>";
53+
private enum Tag {
5354

54-
private static final String ATTRIBUTE_TEMPLATE = " %s=\"%s\"";
55+
collection(" xmlns%s=\"" + NAMESPACE + "\"%s"),
56+
controlfield(" tag=\"%s\""),
57+
datafield(" tag=\"%s\" ind1=\"%s\" ind2=\"%s\""),
58+
leader(""),
59+
record(""),
60+
subfield(" code=\"%s\"");
61+
62+
private static final String OPEN_TEMPLATE = "<%%s%s%s>";
63+
private static final String CLOSE_TEMPLATE = "</%%s%s>";
64+
65+
private final String openTemplate;
66+
private final String closeTemplate;
67+
68+
Tag(final String template) {
69+
openTemplate = String.format(OPEN_TEMPLATE, name(), template);
70+
closeTemplate = String.format(CLOSE_TEMPLATE, name());
71+
}
72+
73+
public String open(final Object[] args) {
74+
return String.format(openTemplate, args);
75+
}
76+
77+
public String close(final Object[] args) {
78+
return String.format(closeTemplate, args);
79+
}
5580

56-
private static final String CONTROLFIELD_OPEN_TEMPLATE = "<marc:controlfield tag=\"%s\">";
57-
private static final String CONTROLFIELD_CLOSE = "</marc:controlfield>";
81+
}
5882

59-
private static final String DATAFIELD_OPEN_TEMPLATE = "<marc:datafield tag=\"%s\" ind1=\"%s\" ind2=\"%s\">";
60-
private static final String DATAFIELD_CLOSE = "</marc:datafield>";
83+
private static final String NAMESPACE = "http://www.loc.gov/MARC21/slim";
84+
private static final String NAMESPACE_NAME = "marc";
85+
private static final String NAMESPACE_PREFIX = NAMESPACE_NAME + ":";
86+
private static final String NAMESPACE_SUFFIX = ":" + NAMESPACE_NAME;
6187

62-
private static final String SUBFIELD_OPEN_TEMPLATE = "<marc:subfield code=\"%s\">";
63-
private static final String SUBFIELD_CLOSE = "</marc:subfield>";
88+
private static final String SCHEMA_ATTRIBUTES = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"" + NAMESPACE + " http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd\"";
6489

65-
private static final String LEADER_OPEN_TEMPLATE = "<marc:leader>";
66-
private static final String LEADER_CLOSE_TEMPLATE = "</marc:leader>";
90+
private static final String ATTRIBUTE_TEMPLATE = " %s=\"%s\"";
6791

6892
private static final String NEW_LINE = "\n";
6993
private static final String INDENT = "\t";
94+
private static final String EMPTY = "";
7095

7196
private static final String XML_DECLARATION_TEMPLATE = "<?xml version=\"%s\" encoding=\"%s\"?>";
7297

@@ -89,6 +114,9 @@ public final class MarcXmlEncoder extends DefaultStreamPipe<ObjectReceiver<Strin
89114

90115
private String currentEntity = "";
91116

117+
private boolean emitNamespace = true;
118+
private Object[] namespacePrefix = new Object[]{emitNamespace ? NAMESPACE_PREFIX : EMPTY};
119+
92120
private int indentationLevel;
93121
private boolean formatted = PRETTY_PRINTED;
94122
private int recordAttributeOffset;
@@ -99,6 +127,11 @@ public final class MarcXmlEncoder extends DefaultStreamPipe<ObjectReceiver<Strin
99127
public MarcXmlEncoder() {
100128
}
101129

130+
public void setEmitNamespace(final boolean emitNamespace) {
131+
this.emitNamespace = emitNamespace;
132+
namespacePrefix = new Object[]{emitNamespace ? NAMESPACE_PREFIX : EMPTY};
133+
}
134+
102135
/**
103136
* Sets the flag to decide whether to omit the XML declaration.
104137
*
@@ -151,14 +184,14 @@ public void startRecord(final String identifier) {
151184
writeHeader();
152185
prettyPrintNewLine();
153186
}
154-
writeRaw(ROOT_OPEN);
187+
writeTag(Tag.collection::open, emitNamespace ? NAMESPACE_SUFFIX : EMPTY, emitNamespace ? SCHEMA_ATTRIBUTES : EMPTY);
155188
prettyPrintNewLine();
156189
incrementIndentationLevel();
157190
}
158191
atStreamStart = false;
159192

160193
prettyPrintIndentation();
161-
writeRaw(RECORD_OPEN);
194+
writeTag(Tag.record::open);
162195
recordAttributeOffset = builder.length() - 1;
163196
prettyPrintNewLine();
164197

@@ -169,7 +202,7 @@ public void startRecord(final String identifier) {
169202
public void endRecord() {
170203
decrementIndentationLevel();
171204
prettyPrintIndentation();
172-
writeRaw(RECORD_CLOSE);
205+
writeTag(Tag.record::close);
173206
prettyPrintNewLine();
174207
sendAndClearData();
175208
}
@@ -188,7 +221,7 @@ public void startEntity(final String name) {
188221
final String ind1 = name.substring(IND1_BEGIN, IND1_END);
189222
final String ind2 = name.substring(IND2_BEGIN, IND2_END);
190223
prettyPrintIndentation();
191-
writeRaw(String.format(DATAFIELD_OPEN_TEMPLATE, tag, ind1, ind2));
224+
writeTag(Tag.datafield::open, tag, ind1, ind2);
192225
prettyPrintNewLine();
193226
incrementIndentationLevel();
194227
}
@@ -199,7 +232,7 @@ public void endEntity() {
199232
if (!currentEntity.equals(Marc21EventNames.LEADER_ENTITY)) {
200233
decrementIndentationLevel();
201234
prettyPrintIndentation();
202-
writeRaw(DATAFIELD_CLOSE);
235+
writeTag(Tag.datafield::close);
203236
prettyPrintNewLine();
204237
}
205238
currentEntity = "";
@@ -215,19 +248,19 @@ public void literal(final String name, final String value) {
215248
}
216249
else if (!writeLeader(name, value)) {
217250
prettyPrintIndentation();
218-
writeRaw(String.format(CONTROLFIELD_OPEN_TEMPLATE, name));
251+
writeTag(Tag.controlfield::open, name);
219252
if (value != null) {
220253
writeEscaped(value.trim());
221254
}
222-
writeRaw(CONTROLFIELD_CLOSE);
255+
writeTag(Tag.controlfield::close);
223256
prettyPrintNewLine();
224257
}
225258
}
226259
else if (!writeLeader(currentEntity, value)) {
227260
prettyPrintIndentation();
228-
writeRaw(String.format(SUBFIELD_OPEN_TEMPLATE, name));
261+
writeTag(Tag.subfield::open, name);
229262
writeEscaped(value.trim());
230-
writeRaw(SUBFIELD_CLOSE);
263+
writeTag(Tag.subfield::close);
231264
prettyPrintNewLine();
232265
}
233266
}
@@ -264,7 +297,7 @@ private void writeHeader() {
264297

265298
/** Closes the root tag */
266299
private void writeFooter() {
267-
writeRaw(ROOT_CLOSE);
300+
writeTag(Tag.collection::close);
268301
}
269302

270303
/**
@@ -288,7 +321,9 @@ private void writeEscaped(final String str) {
288321
private boolean writeLeader(final String name, final String value) {
289322
if (name.equals(Marc21EventNames.LEADER_ENTITY)) {
290323
prettyPrintIndentation();
291-
writeRaw(LEADER_OPEN_TEMPLATE + value + LEADER_CLOSE_TEMPLATE);
324+
writeTag(Tag.leader::open);
325+
writeRaw(value);
326+
writeTag(Tag.leader::close);
292327
prettyPrintNewLine();
293328

294329
return true;
@@ -298,6 +333,12 @@ private boolean writeLeader(final String name, final String value) {
298333
}
299334
}
300335

336+
private void writeTag(final Function<Object[], String> function, final Object... args) {
337+
final Object[] allArgs = Arrays.copyOf(namespacePrefix, namespacePrefix.length + args.length);
338+
System.arraycopy(args, 0, allArgs, namespacePrefix.length, args.length);
339+
writeRaw(function.apply(allArgs));
340+
}
341+
301342
private void prettyPrintIndentation() {
302343
if (formatted) {
303344
final String prefix = String.join("", Collections.nCopies(indentationLevel, INDENT));

metafacture-biblio/src/test/java/org/metafacture/biblio/marc21/MarcXmlEncoderTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,18 @@ public void createTwoRecordsInOneCollection() {
168168
assertEquals(expected, actual);
169169
}
170170

171+
@Test
172+
public void issue403_shouldNotEmitNamespaceIfDisabled() {
173+
encoder.setEmitNamespace(false);
174+
addOneRecord(encoder);
175+
addOneRecord(encoder);
176+
encoder.closeStream();
177+
String expected = XML_DECLARATION + "<collection xmlns=\"http://www.loc.gov/MARC21/slim\">"
178+
+ XML_RECORD + XML_RECORD + XML_MARC_COLLECTION_END_TAG;
179+
String actual = resultCollector.toString();
180+
assertEquals(expected.replace("marc:", ""), actual);
181+
}
182+
171183
@Test(expected = MetafactureException.class)
172184
public void emitExceptionWhenEntityLengthNot5() {
173185
encoder.startRecord(RECORD_ID);

0 commit comments

Comments
 (0)