do not process XML characters outside elements, fix tests to not use temp files with deleteOnExit

This commit is contained in:
Jörg Prante 2023-02-08 13:40:20 +01:00
parent 3aae6c5b7e
commit d971082000
15 changed files with 2664 additions and 2249 deletions

View file

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

View file

@ -338,8 +338,7 @@ public class MarcField implements Comparable<MarcField> {
@Override
public String toString() {
return toKey() + (getValue() != null && !getValue().isEmpty() ? getValue() : "")
+ (!getSubfields().isEmpty() ? getSubfields() : "");
return toKey() + (builder.hasSubfields() ? getSubfields() : getValue());
}
/**
@ -364,6 +363,8 @@ public class MarcField implements Comparable<MarcField> {
private Boolean isControl;
private boolean disableControlFields;
private MarcFieldValidator validator;
Builder() {
@ -622,16 +623,15 @@ public class MarcField implements Comparable<MarcField> {
@SuppressWarnings("unchecked")
public Builder key(List<String> key, Object value) {
switch (key.size()) {
case 0: {
case 0 -> {
if (value instanceof Collection) {
Collection<Map.Entry<String, Object>> collection = (Collection<Map.Entry<String, Object>>) value;
for (Map.Entry<String, Object> entry : collection) {
tag(entry.getKey()).value(entry.getValue().toString());
}
}
break;
}
case 1: {
case 1 -> {
tag(key.get(0));
if (value instanceof Collection) {
Collection<Map.Entry<String, Object>> collection = (Collection<Map.Entry<String, Object>>) value;
@ -641,9 +641,8 @@ public class MarcField implements Comparable<MarcField> {
} else {
value(value.toString());
}
break;
}
case 2: {
case 2 -> {
tag(key.get(0));
String indicator = key.get(1);
if (indicator.isEmpty()) {
@ -659,9 +658,8 @@ public class MarcField implements Comparable<MarcField> {
} else {
value(value.toString());
}
break;
}
case 3: {
case 3 -> {
tag(key.get(0));
String indicator = key.get(1);
if (indicator.isEmpty()) {
@ -681,10 +679,8 @@ public class MarcField implements Comparable<MarcField> {
} else {
subfield(subfieldIds, value.toString());
}
break;
}
default:
throw new IllegalArgumentException("key specification is invalid: " + key);
default -> throw new IllegalArgumentException("key specification is invalid: " + key);
}
return this;
}
@ -694,12 +690,24 @@ public class MarcField implements Comparable<MarcField> {
return this;
}
/**
* For some MARC dialects, we may want to disable control field logic completely.
* @return this builder
*/
public Builder disableControlFields() {
this.disableControlFields = true;
return this;
}
/**
* Is the MARC field a control field?
*
* @return true if control field, false if not
*/
public boolean isControl() {
if (disableControlFields) {
return false;
}
if (isControl == null) {
this.isControl = tag != null && tag.length() >= 2 && tag.charAt(0) == '0' && tag.charAt(1) == '0';
}

View file

@ -31,7 +31,7 @@ import java.util.Set;
*/
public class MabXMLContentHandler extends MarcContentHandler implements MabXMLConstants {
private Set<String> validNamespaces = new HashSet<>(Collections.singletonList(MABXML_NAMESPACE));
private final Set<String> validNamespaces = new HashSet<>(Collections.singletonList(MABXML_NAMESPACE));
public MabXMLContentHandler() {
setTrim(true);
@ -56,15 +56,15 @@ public class MabXMLContentHandler extends MarcContentHandler implements MabXMLCo
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
content.setLength(0);
inelement = true;
if (!isNamespace(uri)) {
return;
}
switch (localName) {
case DATEI: {
case DATEI -> {
beginCollection();
break;
}
case DATENSATZ: {
case DATENSATZ -> {
String type = null;
for (int i = 0; i < atts.getLength(); i++) {
if (TYP.equals(atts.getLocalName(i))) {
@ -79,9 +79,8 @@ public class MabXMLContentHandler extends MarcContentHandler implements MabXMLCo
RecordLabel recordLabel = RecordLabel.builder().setIndicatorLength(1).setSubfieldIdentifierLength(0)
.build();
leader(recordLabel);
break;
}
case FELD: {
case FELD -> {
String tag = null;
StringBuilder sb = new StringBuilder();
sb.setLength(atts.getLength());
@ -99,47 +98,42 @@ public class MabXMLContentHandler extends MarcContentHandler implements MabXMLCo
MarcField.Builder builder = MarcField.builder().tag(tag);
builder.indicator(sb.toString());
stack.push(builder);
break;
}
case UF: {
case UF -> {
stack.peek().subfield(atts.getValue(CODE_ATTRIBUTE), null);
break;
}
default:
break;
default -> {
}
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
inelement = false;
if (!isNamespace(uri)) {
return;
}
switch (localName) {
case DATEI: {
case DATEI -> {
endCollection();
break;
}
case DATENSATZ: {
case DATENSATZ -> {
endRecord();
break;
}
case FELD: {
case FELD -> {
String s = content.toString();
MarcField marcField = stack.pop().value(isTrim ? s.trim() : s).build();
if (marcValueTransformers != null) {
marcField = marcValueTransformers.transformValue(marcField);
}
field(marcField);
break;
}
case UF: {
case UF -> {
String s = content.toString();
stack.peek().subfieldValue(isTrim ? s.trim() : s);
break;
}
default:
break;
default -> {
}
}
content.setLength(0);
}

View file

@ -69,6 +69,7 @@ public class PicaXMLContentHandler extends MarcContentHandler implements PicaCon
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
content.setLength(0);
inelement = true;
if (!isNamespace(uri)) {
return;
}
@ -92,7 +93,10 @@ public class PicaXMLContentHandler extends MarcContentHandler implements PicaCon
indicator = value.substring(3);
}
}
MarcField.Builder builder = MarcField.builder().tag(tag).indicator(indicator);
MarcField.Builder builder = MarcField.builder()
.disableControlFields()
.tag(tag)
.indicator(indicator);
stack.push(builder);
break;
}
@ -107,7 +111,10 @@ public class PicaXMLContentHandler extends MarcContentHandler implements PicaCon
indicator = value.substring(3);
}
}
MarcField.Builder builder = MarcField.builder().tag(tag).indicator(indicator);
MarcField.Builder builder = MarcField.builder()
.disableControlFields()
.tag(tag)
.indicator(indicator);
stack.push(builder);
break;
}
@ -134,7 +141,8 @@ public class PicaXMLContentHandler extends MarcContentHandler implements PicaCon
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
public void endElement(String uri, String localName, String qName) {
inelement = false;
if (!isNamespace(uri)) {
return;
}
@ -175,7 +183,6 @@ public class PicaXMLContentHandler extends MarcContentHandler implements PicaCon
default:
throw new IllegalArgumentException("unknown end element: " + uri + " " + localName + " " + qName);
}
content.setLength(0);
}
@Override

View file

@ -305,10 +305,6 @@ public class MarcJsonWriter extends MarcContentHandler implements Flushable, Clo
}
}
public void write(Map<String, Object> map) {
}
/**
* Write MARC record using fields, indicators, and subfield structures,
* therefore allowing duplicate keys in the output.

View file

@ -65,6 +65,8 @@ public class MarcContentHandler
protected StringBuilder content;
protected boolean inelement;
protected MarcListener marcListener;
protected MarcRecordListener marcRecordListener;
@ -297,18 +299,19 @@ public class MarcContentHandler
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
content.setLength(0);
inelement = true;
if (!isNamespace(uri)) {
return;
}
switch (localName) {
case COLLECTION: {
if (!isCollection) {;
case COLLECTION -> {
if (!isCollection) {
;
beginCollection();
isCollection = true;
}
break;
}
case RECORD: {
case RECORD -> {
String thisformat = null;
String thistype = null;
for (int i = 0; i < atts.getLength(); i++) {
@ -325,13 +328,11 @@ public class MarcContentHandler
thistype = this.type;
}
beginRecord(thisformat, thistype);
break;
}
case LEADER: {
break;
case LEADER -> {
}
case CONTROLFIELD: // fall-through
case DATAFIELD: {
// fall-through
case CONTROLFIELD, DATAFIELD -> {
String tag = null;
StringBuilder sb = new StringBuilder();
sb.setLength(atts.getLength());
@ -364,68 +365,63 @@ public class MarcContentHandler
builder.indicator(sb.substring(min - 1, max));
}
stack.push(builder);
break;
}
case SUBFIELD: {
case SUBFIELD -> {
stack.peek().subfield(atts.getValue(CODE_ATTRIBUTE), null);
break;
}
default:
break;
default -> {
}
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
inelement = false;
if (!isNamespace(uri)) {
return;
}
switch (localName) {
case COLLECTION: {
case COLLECTION -> {
if (isCollection) {
endCollection();
isCollection = false;
}
break;
}
case RECORD: {
case RECORD -> {
endRecord();
break;
}
case LEADER: {
case LEADER -> {
leader(RecordLabel.builder().from(content.toString().toCharArray()).build());
break;
}
case CONTROLFIELD: {
case CONTROLFIELD -> {
MarcField marcField = stack.pop().value(content.toString()).build();
if (marcValueTransformers != null) {
marcField = marcValueTransformers.transformValue(marcField);
}
field(marcField);
break;
}
case DATAFIELD: {
case DATAFIELD -> {
MarcField marcField = stack.pop().build();
if (marcValueTransformers != null) {
marcField = marcValueTransformers.transformValue(marcField);
}
field(marcField);
break;
}
case SUBFIELD: {
case SUBFIELD -> {
String s = content.toString();
stack.peek().subfieldValue(isTrim ? s.trim() : s);
break;
}
default: {
break;
default -> {
}
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
content.append(ch, start, length);
// ignore characters when element has not started
if (inelement) {
content.append(ch, start, length);
}
}
@Override

View file

@ -21,9 +21,9 @@ import org.junit.jupiter.api.Test;
import org.xbib.marc.json.MarcJsonWriter;
import org.xbib.marc.xml.MarcXchangeWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.EnumSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@ -35,46 +35,46 @@ public class ConcurrencyTest {
* Open same file 16 times, but write to a single XML writer.
* We have three streaks:
* <ul>
* <li>file header / collection start (not parallizable)</li>
* <li>file header / collection start (not parallelizable)</li>
* <li>records (can be parallelized, implemented by {@code writeRecords()})</li>
* <li>collection end / file close (not parallizable)</li>
* <li>collection end / file close (not parallelizable)</li>
* </ul>
* @throws Exception if test fails
*/
@Test
public void concurrentXmlWrite() throws Exception {
int n = 16;
ExecutorService executorService = Executors.newFixedThreadPool(n);
String s = "zdblokutf8.mrc";
File file = File.createTempFile(s + ".", ".xml");
file.deleteOnExit();
FileOutputStream out = new FileOutputStream(file);
try (MarcXchangeWriter writer = new MarcXchangeWriter(out, true)
.setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT)
.setType(MarcXchangeConstants.BIBLIOGRAPHIC_TYPE)
) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (MarcXchangeWriter writer = new MarcXchangeWriter(outputStream, true)
.setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT)
.setType(MarcXchangeConstants.BIBLIOGRAPHIC_TYPE)) {
writer.startDocument();
writer.beginCollection();
int n = 16;
ExecutorService executorService = Executors.newFixedThreadPool(n);
for (int i = 0; i < n; i++) {
InputStream inputStream = getClass().getResource(s).openStream();
executorService.submit(() -> {
Marc.builder()
.setInputStream(inputStream)
.setMarcRecordListener(writer)
.build()
.writeRecords();
URL url = getClass().getResource("zdblokutf8.mrc");
if (url != null) {
try (InputStream inputStream = url.openStream()) {
Marc.builder()
.setInputStream(inputStream)
.setMarcRecordListener(writer)
.build()
.writeRecords();
}
}
return true;
});
}
executorService.shutdown();
executorService.awaitTermination(10, TimeUnit.SECONDS);
executorService.awaitTermination(30L, TimeUnit.SECONDS);
writer.endCollection();
writer.endDocument();
assertNull(writer.getException());
assertEquals(n * 293, writer.getRecordCounter());
}
}
/**
* Write MARC records to JSON array.
*
@ -82,31 +82,32 @@ public class ConcurrencyTest {
*/
@Test
public void concurrentJsonArrayWrite() throws Exception {
int n = 16;
ExecutorService executorService = Executors.newFixedThreadPool(n);
String s = "zdblokutf8.mrc";
File file = File.createTempFile(s + ".", ".json");
file.deleteOnExit();
FileOutputStream out = new FileOutputStream(file);
try (MarcJsonWriter writer = new MarcJsonWriter(out)
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (MarcJsonWriter writer = new MarcJsonWriter(outputStream)
.setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT)
.setType(MarcXchangeConstants.BIBLIOGRAPHIC_TYPE)
) {
writer.startDocument();
writer.beginCollection();
int n = 16;
ExecutorService executorService = Executors.newFixedThreadPool(n);
for (int i = 0; i < n; i++) {
InputStream in = getClass().getResource(s).openStream();
executorService.submit(() -> {
Marc.builder()
.setInputStream(in)
.setMarcRecordListener(writer)
.build()
.writeRecords();
URL url = getClass().getResource("zdblokutf8.mrc");
if (url != null) {
try (InputStream inputStream = url.openStream()) {
Marc.builder()
.setInputStream(inputStream)
.setMarcRecordListener(writer)
.build()
.writeRecords();
}
}
return true;
});
}
executorService.shutdown();
executorService.awaitTermination(10, TimeUnit.SECONDS);
executorService.awaitTermination(30L, TimeUnit.SECONDS);
writer.endCollection();
writer.endDocument();
assertNull(writer.getException());
@ -120,32 +121,33 @@ public class ConcurrencyTest {
*/
@Test
public void concurrentJsonLinesWrite() throws Exception {
int n = 16;
ExecutorService executorService = Executors.newFixedThreadPool(n);
String s = "zdblokutf8.mrc";
File file = File.createTempFile(s + ".", ".jsonlines");
file.deleteOnExit();
FileOutputStream out = new FileOutputStream(file);
try (MarcJsonWriter writer = new MarcJsonWriter(out)
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (MarcJsonWriter writer = new MarcJsonWriter(outputStream)
.setStyle(EnumSet.of(MarcJsonWriter.Style.LINES))
.setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT)
.setType(MarcXchangeConstants.BIBLIOGRAPHIC_TYPE)
) {
writer.startDocument();
writer.beginCollection();
int n = 16;
ExecutorService executorService = Executors.newFixedThreadPool(n);
for (int i = 0; i < n; i++) {
InputStream in = getClass().getResource(s).openStream();
executorService.submit(() -> {
Marc.builder()
.setInputStream(in)
.setMarcRecordListener(writer)
.build()
.writeRecords();
URL url = getClass().getResource("zdblokutf8.mrc");
if (url != null) {
try (InputStream inputStream = url.openStream()) {
Marc.builder()
.setInputStream(inputStream)
.setMarcRecordListener(writer)
.build()
.writeRecords();
}
}
return true;
});
}
executorService.shutdown();
executorService.awaitTermination(10, TimeUnit.SECONDS);
executorService.awaitTermination(30L, TimeUnit.SECONDS);
writer.endCollection();
writer.endDocument();
assertNull(writer.getException());

View file

@ -15,36 +15,28 @@
*/
package org.xbib.marc.dialects.aleph;
import static org.hamcrest.MatcherAssert.assertThat;
import org.junit.jupiter.api.Test;
import org.xbib.marc.Marc;
import org.xbib.marc.MarcXchangeConstants;
import org.xbib.marc.StreamMatcher;
import org.xbib.marc.xml.MarcXchangeWriter;
import org.xmlunit.matchers.CompareMatcher;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
public class AlephSequentialTest {
@Test
public void testAlephBatch() throws Exception {
String s = "batch.seq";
InputStream in = getClass().getResource(s).openStream();
File file = File.createTempFile(s, ".xml");
file.deleteOnExit();
FileOutputStream out = new FileOutputStream(file);
try (MarcXchangeWriter writer = new MarcXchangeWriter(out, true)
.setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT)) {
Marc marc = Marc.builder()
.setInputStream(in)
.setCharset(StandardCharsets.UTF_8)
.setMarcListener(writer)
.build();
marc.wrapIntoCollection(marc.aleph());
}
assertThat(file, CompareMatcher.isIdenticalTo(getClass().getResource(s + ".xml").openStream()));
StreamMatcher.xmlMatch(getClass(), "batch.seq", ".xml", (inputStream, outputStream) -> {
try (MarcXchangeWriter writer = new MarcXchangeWriter(outputStream, true)
.setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT)) {
Marc marc = Marc.builder()
.setInputStream(inputStream)
.setCharset(StandardCharsets.UTF_8)
.setMarcListener(writer)
.build();
marc.wrapIntoCollection(marc.aleph());
}
});
}
}

View file

@ -379,5 +379,4 @@ public class MabTest {
writer.close();
}
}
}

View file

@ -15,118 +15,185 @@
*/
package org.xbib.marc.dialects.pica;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.xbib.marc.StreamMatcher.assertStream;
import org.junit.jupiter.api.Test;
import org.xbib.marc.Marc;
import org.xbib.marc.MarcField;
import org.xbib.marc.MarcListener;
import org.xbib.marc.MarcXchangeConstants;
import org.xbib.marc.StreamMatcher;
import org.xbib.marc.label.RecordLabel;
import org.xbib.marc.xml.MarcXchangeWriter;
import org.xmlunit.matchers.CompareMatcher;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class PicaTest {
@Test
public void testPicaBinary() throws Exception {
String s = "pica.binary";
InputStream in = getClass().getResource(s).openStream();
File file = File.createTempFile(s + ".", ".xml");
file.deleteOnExit();
FileOutputStream out = new FileOutputStream(file);
try (MarcXchangeWriter writer = new MarcXchangeWriter(out, true)) {
Marc marc = Marc.builder()
.setInputStream(in)
.setCharset(StandardCharsets.UTF_8)
.setMarcListener(writer)
.build();
marc.wrapIntoCollection(marc.pica());
}
assertThat(file, CompareMatcher.isIdenticalTo(getClass().getResource(s + ".xml").openStream()));
StreamMatcher.fileMatch(getClass(), "pica.binary", ".xml", (inputStream, outputStream) -> {
try (MarcXchangeWriter writer = new MarcXchangeWriter(outputStream, true)) {
Marc marc = Marc.builder()
.setInputStream(inputStream)
.setCharset(StandardCharsets.UTF_8)
.setMarcListener(writer)
.build();
marc.wrapIntoCollection(marc.pica());
}
});
}
@Test
public void testPicaPlain() throws Exception {
for (String s : new String[]{
"pica.plain",
"bgb.example"
}) {
InputStream in = getClass().getResource(s).openStream();
File file = File.createTempFile(s + ".", ".xml");
file.deleteOnExit();
FileOutputStream out = new FileOutputStream(file);
try (MarcXchangeWriter writer = new MarcXchangeWriter(out, true)
StreamMatcher.fileMatch(getClass(), "pica.plain", ".xml", (inputStream, outputStream) -> {
try (MarcXchangeWriter writer = new MarcXchangeWriter(outputStream, true)
.setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT)
.setType(MarcXchangeConstants.BIBLIOGRAPHIC_TYPE)
) {
Marc marc = Marc.builder()
.setInputStream(in)
.setInputStream(inputStream)
.setCharset(StandardCharsets.UTF_8)
.setMarcListener(writer)
.build();
marc.wrapIntoCollection(marc.picaPlain());
}
assertThat(file, CompareMatcher.isIdenticalTo(getClass().getResource(s + ".xml").openStream()));
}
});
}
@Test
public void testPicaXML() throws Exception {
for (String s : new String[]{
"zdb-oai-bib.xml",
"sru_picaxml.xml"
}) {
InputStream in = getClass().getResourceAsStream(s);
StringBuilder sb = new StringBuilder();
public void testBgbExample() throws Exception {
StreamMatcher.fileMatch(getClass(), "bgb.example", ".xml", (inputStream, outputStream) -> {
try (MarcXchangeWriter writer = new MarcXchangeWriter(outputStream, true)
.setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT)
.setType(MarcXchangeConstants.BIBLIOGRAPHIC_TYPE)
) {
Marc marc = Marc.builder()
.setInputStream(inputStream)
.setCharset(StandardCharsets.UTF_8)
.setMarcListener(writer)
.build();
marc.wrapIntoCollection(marc.picaPlain());
}
});
}
MarcListener listener = new MarcListener() {
@Override
public void beginCollection() {
}
@Test
public void testZdbOaiBibXml() throws Exception {
StreamMatcher.fileMatch(getClass(), "zdb-oai-bib.xml", "-keyvalue.txt", (inputStream, outputStream) -> {
try (Listener listener = new Listener(outputStream, StandardCharsets.UTF_8)) {
PicaXMLContentHandler contentHandler = new PicaXMLContentHandler();
contentHandler.setFormat("Pica");
contentHandler.setType("XML");
contentHandler.setMarcListener(listener);
Marc marc = Marc.builder()
.setInputStream(inputStream)
.setContentHandler(contentHandler)
.build();
marc.xmlReader().parse();
}
});
}
@Override
public void endCollection() {
}
@Test
public void testSruPicaXml() throws Exception {
StreamMatcher.fileMatch(getClass(), "sru_picaxml.xml", "-keyvalue.txt", (inputStream, outputStream) -> {
try (Listener listener = new Listener(outputStream, StandardCharsets.UTF_8)) {
PicaXMLContentHandler contentHandler = new PicaXMLContentHandler();
contentHandler.setFormat("Pica");
contentHandler.setType("XML");
contentHandler.setMarcListener(listener);
Marc marc = Marc.builder()
.setInputStream(inputStream)
.setContentHandler(contentHandler)
.build();
marc.xmlReader().parse();
}
});
}
@Override
public void leader(RecordLabel label) {
sb.append("leader=").append(label).append("\n");
}
@Test
public void testDE1a() throws IOException {
StreamMatcher.fileMatch(getClass(), "DE-1a.pp.xml", ".xml", (inputStream, outputStream) -> {
// we can not simply write MarcXchange out of Pica. We will fix it later.
try (MarcXchangeWriter writer = new MarcXchangeWriter(outputStream, true)
.setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT)
.setType(MarcXchangeConstants.BIBLIOGRAPHIC_TYPE)
) {
PicaXMLContentHandler contentHandler = new PicaXMLContentHandler();
contentHandler.setFormat("Pica");
contentHandler.setType("XML");
contentHandler.setMarcListener(writer);
Marc marc = Marc.builder()
.setInputStream(inputStream)
.setContentHandler(contentHandler)
.build();
marc.xmlReader().parse();
}
});
}
@Override
public void beginRecord(String format, String type) {
sb.append("beginRecord\n")
.append("format=").append(format).append("\n")
.append("type=").append(type).append("\n");
}
@Override
public void field(MarcField field) {
sb.append("field=").append(field).append("\n");
}
private static class Listener implements MarcListener, AutoCloseable {
@Override
public void endRecord() {
sb.append("endRecord\n");
}
private final BufferedWriter writer;
};
PicaXMLContentHandler contentHandler = new PicaXMLContentHandler();
contentHandler.setFormat("Pica");
contentHandler.setType("XML");
contentHandler.setMarcListener(listener);
Marc marc = Marc.builder()
.setInputStream(in)
.setContentHandler(contentHandler)
.build();
marc.xmlReader().parse();
assertStream(s, getClass().getResource(s + "-keyvalue.txt").openStream(),
sb.toString());
Listener(OutputStream outputStream, Charset charset) {
this.writer = new BufferedWriter(new OutputStreamWriter(outputStream, charset));
}
@Override
public void beginCollection() {
}
@Override
public void endCollection() {
}
@Override
public void beginRecord(String format, String type) {
try {
writer.append("beginRecord").append("\n");
writer.append("format=").append(format).append("\n");
writer.append("type=").append(type).append("\n");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void leader(RecordLabel label) {
try {
writer.append("leader=").append(label.toString()).append("\n");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void field(MarcField field) {
try {
writer.append("field=").append(field.toString()).append("\n");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void endRecord() {
try {
writer.append("endRecord").append("\n");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void close() throws IOException {
writer.close();
}
}
}

View file

@ -15,20 +15,14 @@
*/
package org.xbib.marc.dialects.sisis;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.xbib.marc.Marc;
import org.xbib.marc.MarcXchangeConstants;
import org.xbib.marc.StreamMatcher;
import org.xbib.marc.transformer.field.MarcFieldTransformer;
import org.xbib.marc.transformer.field.MarcFieldTransformers;
import org.xbib.marc.xml.MarcXchangeWriter;
import org.xmlunit.matchers.CompareMatcher;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
public class SisisTest {
@ -40,20 +34,18 @@ public class SisisTest {
*/
@Test
public void testSisis() throws Exception {
String s = "unloaddipl";
InputStream in = getClass().getResource(s).openStream();
Writer out = new StringWriter();
try (MarcXchangeWriter writer = new MarcXchangeWriter(out)
.setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT)) {
Marc marc = Marc.builder()
.setInputStream(in)
.setCharset(StandardCharsets.UTF_8)
.setMarcListener(writer)
.build();
long l = marc.wrapIntoCollection(marc.sisis());
assertEquals(36353, l);
}
assertThat(out.toString(), CompareMatcher.isIdenticalTo(getClass().getResource(s + ".xml").openStream()));
StreamMatcher.xmlMatch(getClass(), "unloaddipl", ".xml", (inputStream, outputStream) -> {
try (MarcXchangeWriter writer = new MarcXchangeWriter(outputStream)
.setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT)) {
Marc marc = Marc.builder()
.setInputStream(inputStream)
.setCharset(StandardCharsets.UTF_8)
.setMarcListener(writer)
.build();
long l = marc.wrapIntoCollection(marc.sisis());
assertEquals(36353, l);
}
});
}
/**
@ -63,31 +55,27 @@ public class SisisTest {
*/
@Test
public void testSisisMapped() throws Exception {
String s = "testTit.tit";
InputStream in = getClass().getResource(s).openStream();
File file = File.createTempFile(s, ".xml");
file.deleteOnExit();
FileOutputStream out = new FileOutputStream(file);
MarcFieldTransformers transformers = new MarcFieldTransformers();
MarcFieldTransformer t0 = MarcFieldTransformer.builder()
.fromTo("663$01$a", "662$01$x")
.fromTo("663$02$a", "662$02$x")
.fromTo("663$21$a", "662$21$x")
.fromTo("663$22$a", "662$22$x")
.operator(MarcFieldTransformer.Operator.HEAD)
.build();
transformers.add(t0);
try (MarcXchangeWriter writer = new MarcXchangeWriter(out, true)
.setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT)) {
Marc marc = Marc.builder()
.setInputStream(in)
.setCharset(StandardCharsets.UTF_8)
.setMarcListener(writer)
.setMarcFieldTransformers(transformers)
StreamMatcher.xmlMatch(getClass(), "testTit.tit", ".xml", (inputStream, outputStream) -> {
MarcFieldTransformers transformers = new MarcFieldTransformers();
MarcFieldTransformer t0 = MarcFieldTransformer.builder()
.fromTo("663$01$a", "662$01$x")
.fromTo("663$02$a", "662$02$x")
.fromTo("663$21$a", "662$21$x")
.fromTo("663$22$a", "662$22$x")
.operator(MarcFieldTransformer.Operator.HEAD)
.build();
long l = marc.wrapIntoCollection(marc.sisisCRLF());
assertEquals(1246, l);
}
assertThat(file, CompareMatcher.isIdenticalTo(getClass().getResource(s + ".xml").openStream()));
transformers.add(t0);
try (MarcXchangeWriter writer = new MarcXchangeWriter(outputStream, true)
.setFormat(MarcXchangeConstants.MARCXCHANGE_FORMAT)) {
Marc marc = Marc.builder()
.setInputStream(inputStream)
.setCharset(StandardCharsets.UTF_8)
.setMarcListener(writer)
.setMarcFieldTransformers(transformers)
.build();
long l = marc.wrapIntoCollection(marc.sisisCRLF());
assertEquals(1246, l);
}
});
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,169 @@
<?xml version="1.0" ?>
<ppxml:record xmlns:ppxml="http://www.oclcpica.org/xmlns/ppxml-1.0">
<ppxml:global opacflag="" status="">
<ppxml:tag id="00900004" occ=""></ppxml:tag>
<ppxml:tag id="001A" occ="">
<ppxml:subf id="0">9006:18-11-99</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="001B" occ="">
<ppxml:subf id="0">9006:11-02-20</ppxml:subf>
<ppxml:subf id="t">16:54:10.000</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="001D" occ="">
<ppxml:subf id="0">9999:27-05-05</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="001U" occ="">
<ppxml:subf id="0">utf8</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="001X" occ="">
<ppxml:subf id="0">0</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="002@" occ="">
<ppxml:subf id="0">Tw</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="003@" occ="">
<ppxml:subf id="0">009000046</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="008H" occ="">
<ppxml:subf id="a">101005-0</ppxml:subf>
<ppxml:subf id="b">AK001</ppxml:subf>
<ppxml:subf id="d">1a</ppxml:subf>
<ppxml:subf id="e">DE-1a</ppxml:subf>
<ppxml:subf id="f">SBBPK</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="009Q" occ="">
<ppxml:subf id="u">http://www.staatsbibliothek-berlin.de</ppxml:subf>
<ppxml:subf id="z">A</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="009Q" occ="">
<ppxml:subf id="u">http://stabikat.de</ppxml:subf>
<ppxml:subf id="z">B</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="009Q" occ="">
<ppxml:subf id="u">http://staatsbibliothek-berlin.de/service/auskunft/</ppxml:subf>
<ppxml:subf id="x">Online-Auskunft</ppxml:subf>
<ppxml:subf id="z">W</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="009Q" occ="">
<ppxml:subf id="u">https://staatsbibliothek-berlin.de/vor-ort/opening-hours/</ppxml:subf>
<ppxml:subf id="x">O&#776;ffnungszeiten besonderer Bereiche</ppxml:subf>
<ppxml:subf id="z">W</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="029@" occ="">
<ppxml:subf id="a">SBB-PK, Potsdamer Stra&#223;e</ppxml:subf>
<ppxml:subf id="4">a</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="029@" occ="">
<ppxml:subf id="a">Berlin SBB Haus Potsdamer Str</ppxml:subf>
<ppxml:subf id="4">c</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="029A" occ="">
<ppxml:subf id="a">Staatsbibliothek zu Berlin - Preu&#223;ischer Kulturbesitz, Haus Potsdamer Stra&#223;e</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="032P" occ="">
<ppxml:subf id="a">Potsdamer Str. 33</ppxml:subf>
<ppxml:subf id="b">Berlin</ppxml:subf>
<ppxml:subf id="d">DE</ppxml:subf>
<ppxml:subf id="e">10785</ppxml:subf>
<ppxml:subf id="f">Berlin</ppxml:subf>
<ppxml:subf id="i">Mo-Sa 8.00-22.00</ppxml:subf>
<ppxml:subf id="j">Servicezeiten und O&#776;ffnungszeiten besonderer Bereiche s. Link &quot;O&#776;ffnungszeiten besonderer Bereiche&quot;</ppxml:subf>
<ppxml:subf id="k">13.37063</ppxml:subf>
<ppxml:subf id="l">52.50771</ppxml:subf>
<ppxml:subf id="n">11000000</ppxml:subf>
<ppxml:subf id="p">j</ppxml:subf>
<ppxml:subf id="2">S</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="032P" occ="">
<ppxml:subf id="b">Berlin</ppxml:subf>
<ppxml:subf id="d">DE</ppxml:subf>
<ppxml:subf id="e">10772</ppxml:subf>
<ppxml:subf id="f">Berlin</ppxml:subf>
<ppxml:subf id="p">j</ppxml:subf>
<ppxml:subf id="2">P</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="035B" occ="">
<ppxml:subf id="a">S</ppxml:subf>
<ppxml:subf id="c">j</ppxml:subf>
<ppxml:subf id="d">49</ppxml:subf>
<ppxml:subf id="e">30</ppxml:subf>
<ppxml:subf id="f">2 66-433888</ppxml:subf>
<ppxml:subf id="g">49</ppxml:subf>
<ppxml:subf id="h">30</ppxml:subf>
<ppxml:subf id="i">2 66-333501</ppxml:subf>
<ppxml:subf id="k">info@sbb.spk-berlin.de</ppxml:subf>
<ppxml:subf id="l">Auskunft</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="035B" occ="">
<ppxml:subf id="a">W</ppxml:subf>
<ppxml:subf id="b">Benutzung</ppxml:subf>
<ppxml:subf id="c">j</ppxml:subf>
<ppxml:subf id="k">benutzung.h2@sbb.spk-berlin.de</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="035D" occ="">
<ppxml:subf id="a">B 3</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="035D" occ="">
<ppxml:subf id="a">He 201</ppxml:subf>
<ppxml:subf id="b">DE-He201</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="035E" occ="">
<ppxml:subf id="a">H</ppxml:subf>
<ppxml:subf id="b">s</ppxml:subf>
<ppxml:subf id="c">0011</ppxml:subf>
<ppxml:subf id="e">GBV</ppxml:subf>
<ppxml:subf id="f">11</ppxml:subf>
<ppxml:subf id="g">07</ppxml:subf>
<ppxml:subf id="h">10</ppxml:subf>
<ppxml:subf id="l">CC0</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="035G" occ="">
<ppxml:subf id="a">Recht</ppxml:subf>
<ppxml:subf id="a">Orientalistik</ppxml:subf>
<ppxml:subf id="a">Osteuropa</ppxml:subf>
<ppxml:subf id="a">Ostasien</ppxml:subf>
<ppxml:subf id="a">Afrika</ppxml:subf>
<ppxml:subf id="a">Amtsdruckschriften</ppxml:subf>
<ppxml:subf id="a">Handschriften</ppxml:subf>
<ppxml:subf id="a">Karten</ppxml:subf>
<ppxml:subf id="a">Geistes- und Sozialwissenschaften</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="035H" occ="">
<ppxml:subf id="a">FID-INTRECHT-DE-1a / FID internationale und interdisziplina&#776;re Rechtsforschung (ab 2014)</ppxml:subf>
<ppxml:subf id="a">FID-ASIEN-DE-1a / FID Asien &#8211; CrossAsia (ab 2016)</ppxml:subf>
<ppxml:subf id="a">FID-KARTEN-DE-1a / FID Kartographie und Geobasisdaten (ab 2016)</ppxml:subf>
<ppxml:subf id="a">FID-SLAW-DE-1a / FID Slawistik (ab 2016)</ppxml:subf>
<ppxml:subf id="a">SSG 2 / Rechtswissenschaft (bis einschlie&#223;lich 2015)</ppxml:subf>
<ppxml:subf id="a">SSG 6,25 / Ost- und Su&#776;dostasien (bis einschlie&#223;lich 2015)</ppxml:subf>
<ppxml:subf id="a">SSG 7,39 / Slawistik (bis einschlie&#223;lich 2015)</ppxml:subf>
<ppxml:subf id="a">SSG 14,1 / Vero&#776;ffentlichungen zur Kartographie (bis einschlie&#223;lich 2015)</ppxml:subf>
<ppxml:subf id="a">SSG 27 / Parlamentsschriften (bis einschlie&#223;lich 2015)</ppxml:subf>
<ppxml:subf id="a">SSG 28,1 / Topographische Karten (bis einschlie&#223;lich 2015)</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="035I" occ="">
<ppxml:subf id="a">BER</ppxml:subf>
<ppxml:subf id="b">U&#776;LV</ppxml:subf>
<ppxml:subf id="c">GBV</ppxml:subf>
<ppxml:subf id="d">Kalliope</ppxml:subf>
<ppxml:subf id="e">l</ppxml:subf>
<ppxml:subf id="g">V</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="035K" occ="">
<ppxml:subf id="a">S</ppxml:subf>
<ppxml:subf id="b">A</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="035O" occ="">
<ppxml:subf id="a">FZL DE-622</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="047A" occ="">
<ppxml:subf id="a">UNO- und UNESCO-Deposita&#776;rbibliothek. U&#776;bernommene Bibliothek: B 3 (Bibliothek der ehemaligen Preu&#223;ischen Geologischen Landesanstalt)</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="050C" occ="">
<ppxml:subf id="a">ABZ eingetragen 15062015</ppxml:subf>
<ppxml:subf id="5">DE-601</ppxml:subf>
</ppxml:tag>
<ppxml:tag id="050D" occ="">
<ppxml:subf id="a">ANF2020; DE-1a 30-05-07 L SSG 6,20 K Tel.; ZRB 25-07-13 SSG gepru&#776;ft, 7.40 gestrichen, sonst ok; ZRB 17-10-13 N EZB-ID (Rol); ZRB 02-11-16 SSG(s) mit 2015 abgeschlossen; ZRB 18-01-17 DE-He201 u&#776;bernommen; Auftragsbesta&#776;tigung: 11.02.2020 um 16.03</ppxml:subf>
</ppxml:tag>
</ppxml:global>
</ppxml:record>

View file

@ -0,0 +1,197 @@
<record xmlns="info:lc/xmlns/marcxchange-v2" format="MarcXchange" xsi:schemaLocation="info:lc/xmlns/marcxchange-v2 http://www.loc.gov/standards/iso25577/marcxchange-2-0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" type="Bibliographic">
<leader>00000 1000000 000 </leader>
<datafield ind2="0" ind1="0" tag="009"></datafield>
<datafield ind2=" " ind1="A" tag="001">
<subfield code="0">9006:18-11-99</subfield>
<subfield code=" ">9006:18-11-99</subfield>
</datafield>
<datafield ind2=" " ind1="B" tag="001">
<subfield code="0">9006:11-02-20</subfield>
<subfield code="t">16:54:10.000</subfield>
<subfield code=" ">16:54:10.000</subfield>
</datafield>
<datafield ind2=" " ind1="D" tag="001">
<subfield code="0">9999:27-05-05</subfield>
<subfield code=" ">9999:27-05-05</subfield>
</datafield>
<datafield ind2=" " ind1="U" tag="001">
<subfield code="0">utf8</subfield>
<subfield code=" ">utf8</subfield>
</datafield>
<datafield ind2=" " ind1="X" tag="001">
<subfield code="0">0</subfield>
<subfield code=" ">0</subfield>
</datafield>
<datafield ind2=" " ind1="@" tag="002">
<subfield code="0">Tw</subfield>
<subfield code=" ">Tw</subfield>
</datafield>
<datafield ind2=" " ind1="@" tag="003">
<subfield code="0">009000046</subfield>
<subfield code=" ">009000046</subfield>
</datafield>
<datafield ind2=" " ind1="H" tag="008">
<subfield code="a">101005-0</subfield>
<subfield code="b">AK001</subfield>
<subfield code="d">1a</subfield>
<subfield code="e">DE-1a</subfield>
<subfield code="f">SBBPK</subfield>
<subfield code=" ">SBBPK</subfield>
</datafield>
<datafield ind2=" " ind1="Q" tag="009">
<subfield code="u">http://www.staatsbibliothek-berlin.de</subfield>
<subfield code="z">A</subfield>
<subfield code=" ">A</subfield>
</datafield>
<datafield ind2=" " ind1="Q" tag="009">
<subfield code="u">http://stabikat.de</subfield>
<subfield code="z">B</subfield>
<subfield code=" ">B</subfield>
</datafield>
<datafield ind2=" " ind1="Q" tag="009">
<subfield code="u">http://staatsbibliothek-berlin.de/service/auskunft/</subfield>
<subfield code="x">Online-Auskunft</subfield>
<subfield code="z">W</subfield>
<subfield code=" ">W</subfield>
</datafield>
<datafield ind2=" " ind1="Q" tag="009">
<subfield code="u">https://staatsbibliothek-berlin.de/vor-ort/opening-hours/</subfield>
<subfield code="x">Öffnungszeiten besonderer Bereiche</subfield>
<subfield code="z">W</subfield>
<subfield code=" ">W</subfield>
</datafield>
<datafield ind2=" " ind1="@" tag="029">
<subfield code="a">SBB-PK, Potsdamer Straße</subfield>
<subfield code="4">a</subfield>
<subfield code=" ">a</subfield>
</datafield>
<datafield ind2=" " ind1="@" tag="029">
<subfield code="a">Berlin SBB Haus Potsdamer Str</subfield>
<subfield code="4">c</subfield>
<subfield code=" ">c</subfield>
</datafield>
<datafield ind2=" " ind1="A" tag="029">
<subfield code="a">Staatsbibliothek zu Berlin - Preußischer Kulturbesitz, Haus Potsdamer Straße</subfield>
<subfield code=" ">Staatsbibliothek zu Berlin - Preußischer Kulturbesitz, Haus Potsdamer Straße</subfield>
</datafield>
<datafield ind2=" " ind1="P" tag="032">
<subfield code="a">Potsdamer Str. 33</subfield>
<subfield code="b">Berlin</subfield>
<subfield code="d">DE</subfield>
<subfield code="e">10785</subfield>
<subfield code="f">Berlin</subfield>
<subfield code="i">Mo-Sa 8.00-22.00</subfield>
<subfield code="j">Servicezeiten und Öffnungszeiten besonderer Bereiche s. Link "Öffnungszeiten besonderer Bereiche"</subfield>
<subfield code="k">13.37063</subfield>
<subfield code="l">52.50771</subfield>
<subfield code="n">11000000</subfield>
<subfield code="p">j</subfield>
<subfield code="2">S</subfield>
<subfield code=" ">S</subfield>
</datafield>
<datafield ind2=" " ind1="P" tag="032">
<subfield code="b">Berlin</subfield>
<subfield code="d">DE</subfield>
<subfield code="e">10772</subfield>
<subfield code="f">Berlin</subfield>
<subfield code="p">j</subfield>
<subfield code="2">P</subfield>
<subfield code=" ">P</subfield>
</datafield>
<datafield ind2=" " ind1="B" tag="035">
<subfield code="a">S</subfield>
<subfield code="c">j</subfield>
<subfield code="d">49</subfield>
<subfield code="e">30</subfield>
<subfield code="f">2 66-433888</subfield>
<subfield code="g">49</subfield>
<subfield code="h">30</subfield>
<subfield code="i">2 66-333501</subfield>
<subfield code="k">info@sbb.spk-berlin.de</subfield>
<subfield code="l">Auskunft</subfield>
<subfield code=" ">Auskunft</subfield>
</datafield>
<datafield ind2=" " ind1="B" tag="035">
<subfield code="a">W</subfield>
<subfield code="b">Benutzung</subfield>
<subfield code="c">j</subfield>
<subfield code="k">benutzung.h2@sbb.spk-berlin.de</subfield>
<subfield code=" ">benutzung.h2@sbb.spk-berlin.de</subfield>
</datafield>
<datafield ind2=" " ind1="D" tag="035">
<subfield code="a">B 3</subfield>
<subfield code=" ">B 3</subfield>
</datafield>
<datafield ind2=" " ind1="D" tag="035">
<subfield code="a">He 201</subfield>
<subfield code="b">DE-He201</subfield>
<subfield code=" ">DE-He201</subfield>
</datafield>
<datafield ind2=" " ind1="E" tag="035">
<subfield code="a">H</subfield>
<subfield code="b">s</subfield>
<subfield code="c">0011</subfield>
<subfield code="e">GBV</subfield>
<subfield code="f">11</subfield>
<subfield code="g">07</subfield>
<subfield code="h">10</subfield>
<subfield code="l">CC0</subfield>
<subfield code=" ">CC0</subfield>
</datafield>
<datafield ind2=" " ind1="G" tag="035">
<subfield code="a">Recht</subfield>
<subfield code="a">Orientalistik</subfield>
<subfield code="a">Osteuropa</subfield>
<subfield code="a">Ostasien</subfield>
<subfield code="a">Afrika</subfield>
<subfield code="a">Amtsdruckschriften</subfield>
<subfield code="a">Handschriften</subfield>
<subfield code="a">Karten</subfield>
<subfield code="a">Geistes- und Sozialwissenschaften</subfield>
<subfield code=" ">Geistes- und Sozialwissenschaften</subfield>
</datafield>
<datafield ind2=" " ind1="H" tag="035">
<subfield code="a">FID-INTRECHT-DE-1a / FID internationale und interdisziplinäre Rechtsforschung (ab 2014)</subfield>
<subfield code="a">FID-ASIEN-DE-1a / FID Asien CrossAsia (ab 2016)</subfield>
<subfield code="a">FID-KARTEN-DE-1a / FID Kartographie und Geobasisdaten (ab 2016)</subfield>
<subfield code="a">FID-SLAW-DE-1a / FID Slawistik (ab 2016)</subfield>
<subfield code="a">SSG 2 / Rechtswissenschaft (bis einschließlich 2015)</subfield>
<subfield code="a">SSG 6,25 / Ost- und Südostasien (bis einschließlich 2015)</subfield>
<subfield code="a">SSG 7,39 / Slawistik (bis einschließlich 2015)</subfield>
<subfield code="a">SSG 14,1 / Veröffentlichungen zur Kartographie (bis einschließlich 2015)</subfield>
<subfield code="a">SSG 27 / Parlamentsschriften (bis einschließlich 2015)</subfield>
<subfield code="a">SSG 28,1 / Topographische Karten (bis einschließlich 2015)</subfield>
<subfield code=" ">SSG 28,1 / Topographische Karten (bis einschließlich 2015)</subfield>
</datafield>
<datafield ind2=" " ind1="I" tag="035">
<subfield code="a">BER</subfield>
<subfield code="b">ÜLV</subfield>
<subfield code="c">GBV</subfield>
<subfield code="d">Kalliope</subfield>
<subfield code="e">l</subfield>
<subfield code="g">V</subfield>
<subfield code=" ">V</subfield>
</datafield>
<datafield ind2=" " ind1="K" tag="035">
<subfield code="a">S</subfield>
<subfield code="b">A</subfield>
<subfield code=" ">A</subfield>
</datafield>
<datafield ind2=" " ind1="O" tag="035">
<subfield code="a">FZL DE-622</subfield>
<subfield code=" ">FZL DE-622</subfield>
</datafield>
<datafield ind2=" " ind1="A" tag="047">
<subfield code="a">UNO- und UNESCO-Depositärbibliothek. Übernommene Bibliothek: B 3 (Bibliothek der ehemaligen Preußischen Geologischen Landesanstalt)</subfield>
<subfield code=" ">UNO- und UNESCO-Depositärbibliothek. Übernommene Bibliothek: B 3 (Bibliothek der ehemaligen Preußischen Geologischen Landesanstalt)</subfield>
</datafield>
<datafield ind2=" " ind1="C" tag="050">
<subfield code="a">ABZ eingetragen 15062015</subfield>
<subfield code="5">DE-601</subfield>
<subfield code=" ">DE-601</subfield>
</datafield>
<datafield ind2=" " ind1="D" tag="050">
<subfield code="a">ANF2020; DE-1a 30-05-07 L SSG 6,20 K Tel.; ZRB 25-07-13 SSG geprüft, 7.40 gestrichen, sonst ok; ZRB 17-10-13 N EZB-ID (Rol); ZRB 02-11-16 SSG(s) mit 2015 abgeschlossen; ZRB 18-01-17 DE-He201 übernommen; Auftragsbestätigung: 11.02.2020 um 16.03</subfield>
<subfield code=" ">ANF2020; DE-1a 30-05-07 L SSG 6,20 K Tel.; ZRB 25-07-13 SSG geprüft, 7.40 gestrichen, sonst ok; ZRB 17-10-13 N EZB-ID (Rol); ZRB 02-11-16 SSG(s) mit 2015 abgeschlossen; ZRB 18-01-17 DE-He201 übernommen; Auftragsbestätigung: 11.02.2020 um 16.03</subfield>
</datafield>
</record>

File diff suppressed because it is too large Load diff