fix NPE in XML writing, restore MAB hack for subfield 'a' in control field

This commit is contained in:
Jörg Prante 2022-12-12 13:58:44 +01:00
parent e99f75c473
commit 52b4462332
7 changed files with 42 additions and 16 deletions

View file

@ -1,5 +1,5 @@
group = org.xbib group = org.xbib
name = marc name = marc
version = 2.9.11 version = 2.9.13
org.gradle.warning.mode = ALL org.gradle.warning.mode = ALL

View file

@ -714,6 +714,16 @@ public class MarcField implements Comparable<MarcField> {
} }
} }
/**
* Helper method to create a subfield.
* @param id the subfield ID
* @param value the subfeild value
* @return the subfield
*/
public static Subfield subfield(String id, String value) {
return new Subfield(id, value);
}
/** /**
* MARC subfield. A subfield consists of an ID and a value. * MARC subfield. A subfield consists of an ID and a value.
*/ */

View file

@ -159,6 +159,12 @@ public class MarcRecord implements Map<String, Object> {
return recordLabel; return recordLabel;
} }
public void filterFields(Predicate<? super MarcField> predicate) {
if (marcFields != null) {
marcFields = marcFields.stream().filter(predicate).toList();
}
}
/** /**
* Return the MARC fields of this record. * Return the MARC fields of this record.
* *
@ -376,7 +382,7 @@ public class MarcRecord implements Map<String, Object> {
this.delegate = createMapFromMarcFields(Comparator.naturalOrder()); this.delegate = createMapFromMarcFields(Comparator.naturalOrder());
} }
public void rebuildFields(Comparator<MarcField> comparator) { public void sortFields(Comparator<MarcField> comparator) {
this.marcFields.sort(comparator); this.marcFields.sort(comparator);
} }

View file

@ -346,21 +346,22 @@ public class MarcXchangeWriter extends MarcContentHandler implements Flushable,
return; return;
} }
if (field.isControl()) { if (field.isControl()) {
Iterator<Attribute> attrs =
Collections.singletonList(eventFactory.createAttribute(TAG_ATTRIBUTE,
transform(field.getTag()))).iterator();
xmlEventConsumer.add(eventFactory.createStartElement(getControlfieldElement(), attrs, namespaces));
String value = field.getValue(); String value = field.getValue();
if (value != null && !value.isEmpty()) { if (value == null || value.isEmpty()) {
xmlEventConsumer.add(eventFactory.createCharacters(transform(value)));
} else {
// the control field is disguised as a data field, try lookup value in first subfield of " " // the control field is disguised as a data field, try lookup value in first subfield of " "
value = field.getFirstSubfieldValue(" "); value = field.getFirstSubfieldValue(" ");
if (value != null && !value.isEmpty()) { // still no value? Then it is some exotic like MAB with subfield "a"?
xmlEventConsumer.add(eventFactory.createCharacters(transform(value))); if (value == null || value.isEmpty()) {
value = field.getFirstSubfieldValue("a");
} }
} }
xmlEventConsumer.add(eventFactory.createEndElement(getControlfieldElement(), namespaces)); if (value != null && !value.isEmpty()) {
Iterator<Attribute> attrs = Collections.singletonList(eventFactory.createAttribute(TAG_ATTRIBUTE,
transform(field.getTag()))).iterator();
xmlEventConsumer.add(eventFactory.createStartElement(getControlfieldElement(), attrs, namespaces));
xmlEventConsumer.add(eventFactory.createCharacters(transform(value)));
xmlEventConsumer.add(eventFactory.createEndElement(getControlfieldElement(), namespaces));
}
} else if (!field.isEmpty()) { } else if (!field.isEmpty()) {
String tag = field.getTag(); String tag = field.getTag();
String indicator = field.getIndicator(); String indicator = field.getIndicator();
@ -372,6 +373,12 @@ public class MarcXchangeWriter extends MarcContentHandler implements Flushable,
attrs.add(eventFactory.createAttribute(IND_ATTRIBUTE + "2", transform(ind2))); attrs.add(eventFactory.createAttribute(IND_ATTRIBUTE + "2", transform(ind2)));
xmlEventConsumer.add(eventFactory.createStartElement(getDatafieldElement(), attrs.iterator(), namespaces)); xmlEventConsumer.add(eventFactory.createStartElement(getDatafieldElement(), attrs.iterator(), namespaces));
for (MarcField.Subfield subfield : field.getSubfields()) { for (MarcField.Subfield subfield : field.getSubfields()) {
String value = subfield.getValue();
// we skip null values because XML event consumer will fail on length() with NPE.
// we do not skip empty values because of subfield ID transport in MAB or UNIMARC.
if (value == null) {
continue;
}
String code = subfield.getId(); String code = subfield.getId();
// From https://www.loc.gov/standards/iso25577/ISO_DIS_25577_2(E)070727.doc // From https://www.loc.gov/standards/iso25577/ISO_DIS_25577_2(E)070727.doc
// "There is one restriction. A special mode (identifier length = 0) of ISO 2709 operates with // "There is one restriction. A special mode (identifier length = 0) of ISO 2709 operates with
@ -385,7 +392,7 @@ public class MarcXchangeWriter extends MarcContentHandler implements Flushable,
subfieldattrs.add(eventFactory.createAttribute(CODE_ATTRIBUTE, transform(code))); subfieldattrs.add(eventFactory.createAttribute(CODE_ATTRIBUTE, transform(code)));
xmlEventConsumer.add(eventFactory.createStartElement(getSubfieldElement(), xmlEventConsumer.add(eventFactory.createStartElement(getSubfieldElement(),
subfieldattrs.iterator(), namespaces)); subfieldattrs.iterator(), namespaces));
xmlEventConsumer.add(eventFactory.createCharacters(transform(subfield.getValue()))); xmlEventConsumer.add(eventFactory.createCharacters(transform(value)));
xmlEventConsumer.add(eventFactory.createEndElement(getSubfieldElement(), namespaces)); xmlEventConsumer.add(eventFactory.createEndElement(getSubfieldElement(), namespaces));
} }
String value = field.getValue(); String value = field.getValue();

View file

@ -26,6 +26,9 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.xbib.marc.Marc; import org.xbib.marc.Marc;
import org.xbib.marc.MarcField; import org.xbib.marc.MarcField;

View file

@ -7,8 +7,8 @@
<datafield ind2=" " ind1=" " tag="FMT"> <datafield ind2=" " ind1=" " tag="FMT">
<subfield code=" ">MH</subfield> <subfield code=" ">MH</subfield>
</datafield> </datafield>
<controlfield tag="001"></controlfield> <controlfield tag="001">HT004330420</controlfield>
<controlfield tag="002"></controlfield> <controlfield tag="002">19921110</controlfield>
<datafield ind2=" " ind1=" " tag="030"> <datafield ind2=" " ind1=" " tag="030">
<subfield code=" ">a|1uc||||||17</subfield> <subfield code=" ">a|1uc||||||17</subfield>
</datafield> </datafield>

File diff suppressed because one or more lines are too long