Skip to content

Commit 244e60d

Browse files
authored
Merge pull request #761 from metafacture/530-addPicaXmlHandler
Add true picaxml handler #530
2 parents b5741ac + 36f67eb commit 244e60d

5 files changed

Lines changed: 552 additions & 27 deletions

File tree

metafacture-biblio/src/main/java/org/metafacture/biblio/pica/PicaXmlHandler.java

Lines changed: 78 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014 hbz, Pascal Christoph
2+
* Copyright 2026 hbz, Deutsche Nationalbibliothek
33
*
44
* Licensed under the Apache License, Version 2.0 the "License";
55
* you may not use this file except in compliance with the License.
@@ -29,71 +29,122 @@
2929

3030
import java.text.Normalizer;
3131

32+
3233
/**
33-
* A pica xml handler.
34-
*
35-
* @author Pascal Christoph (dr0i)
34+
* A Pica XML reader. To read marc data without namespace specification set option `namespace=""` or to null when using JAVA code.
35+
* The handler reuses some code from M. Geipels MarcXmlHandler
36+
* @author Tobias Bülte
37+
* @author Markus Michael Geipel
3638
*
3739
*/
38-
@Description("A pica xml reader")
40+
@Description("A Pica XML reader. To read pica data without namespace specification set option `namespace=\"\"`. To ignore namespace specification set option `ignorenamespace=\"true\". For PPXML see `handle-ppxml`")
3941
@In(XmlReceiver.class)
4042
@Out(StreamReceiver.class)
4143
@FluxCommand("handle-picaxml")
4244
public final class PicaXmlHandler extends DefaultXmlPipe<StreamReceiver> {
4345

44-
private static final String SUBFIELD = "subf";
45-
private static final String DATAFIELD = "tag";
46+
public static final String NAMESPACE = "info:srw/schema/5/picaXML-v1.0";
47+
48+
private static final String SUBFIELD = "subfield";
49+
private static final String DATAFIELD = "datafield";
4650
private static final String RECORD = "record";
47-
private static final String NAMESPACE =
48-
"http://www.oclcpica.org/xmlns/ppxml-1.0";
49-
private static final String LEADER = "global";
51+
52+
private String attributeMarker = DEFAULT_ATTRIBUTE_MARKER;
5053
private String currentTag = "";
54+
private String namespace = NAMESPACE;
5155
private StringBuilder builder = new StringBuilder();
56+
private boolean ignoreNamespace;
5257

5358
/**
5459
* Creates an instance of {@link PicaXmlHandler}.
5560
*/
5661
public PicaXmlHandler() {
5762
}
5863

64+
/**
65+
* Sets the namespace.
66+
*
67+
* <strong>Default value: {@value #NAMESPACE}</strong>
68+
*
69+
* @param namespace the namespace. Set to null if namespace shouldn't be checked. Set to empty string
70+
* if the namespace is missing in the data.
71+
*/
72+
public void setNamespace(final String namespace) {
73+
this.namespace = namespace;
74+
}
75+
76+
/**
77+
* Sets whether to ignore the namespace.
78+
*
79+
* <strong>Default value: false</strong>
80+
*
81+
* @param ignoreNamespace true if the namespace should be ignored
82+
*/
83+
public void setIgnoreNamespace(final boolean ignoreNamespace) {
84+
this.ignoreNamespace = ignoreNamespace;
85+
}
86+
87+
private boolean checkNamespace(final String uri) {
88+
return namespace == null || ignoreNamespace || namespace.equals(uri);
89+
}
90+
91+
/**
92+
* Sets the attribute marker.
93+
*
94+
* <strong>Default value:
95+
* {@value org.metafacture.framework.helpers.DefaultXmlPipe#DEFAULT_ATTRIBUTE_MARKER}</strong>
96+
*
97+
* @param attributeMarker the attribute marker
98+
*/
99+
public void setAttributeMarker(final String attributeMarker) {
100+
this.attributeMarker = attributeMarker;
101+
}
102+
103+
/**
104+
* Gets the attribute marker.
105+
*
106+
* @return the attribute marker
107+
*/
108+
public String getAttributeMarker() {
109+
return attributeMarker;
110+
}
111+
59112
@Override
60-
public void startElement(final String uri, final String localName,
61-
final String qName, final Attributes attributes) throws SAXException {
113+
public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) throws SAXException {
62114
if (SUBFIELD.equals(localName)) {
63115
builder = new StringBuilder();
64-
currentTag = attributes.getValue("id");
116+
currentTag = attributes.getValue("code");
65117
}
66118
else if (DATAFIELD.equals(localName)) {
67-
getReceiver().startEntity(
68-
attributes.getValue("id") + attributes.getValue("occ"));
119+
final String tag = attributes.getValue("tag");
120+
final String occurence = attributes.getValue("occurrence");
121+
if (occurence != null) {
122+
getReceiver().startEntity(tag + "/" + occurence);
123+
}
124+
else {
125+
getReceiver().startEntity(tag);
126+
}
69127
}
70-
else if (RECORD.equals(localName) && NAMESPACE.equals(uri)) {
128+
else if (RECORD.equals(localName) && checkNamespace(uri)) {
71129
getReceiver().startRecord("");
72130
}
73-
else if (LEADER.equals(localName)) {
74-
builder = new StringBuilder();
75-
currentTag = LEADER;
76-
}
77131
}
78132

79133
@Override
80-
public void endElement(final String uri, final String localName,
81-
final String qName) throws SAXException {
134+
public void endElement(final String uri, final String localName, final String qName) throws SAXException {
82135
if (SUBFIELD.equals(localName)) {
83-
getReceiver().literal(currentTag,
84-
Normalizer.normalize(builder.toString().trim(), Normalizer.Form.NFC));
136+
getReceiver().literal(currentTag, Normalizer.normalize(builder.toString().trim(), Normalizer.Form.NFC));
85137
}
86138
else if (DATAFIELD.equals(localName)) {
87139
getReceiver().endEntity();
88140
}
89-
else if (RECORD.equals(localName) && NAMESPACE.equals(uri)) {
141+
else if (RECORD.equals(localName) && checkNamespace(uri)) {
90142
getReceiver().endRecord();
91143
}
92144
}
93145

94146
@Override
95-
public void characters(final char[] chars, final int start, final int length)
96-
throws SAXException {
147+
public void characters(final char[] chars, final int start, final int length) throws SAXException {
97148
builder.append(chars, start, length);
98149
}
99150

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright 2014 hbz, Pascal Christoph
3+
*
4+
* Licensed under the Apache License, Version 2.0 the "License";
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.metafacture.biblio.pica;
18+
19+
import org.metafacture.framework.FluxCommand;
20+
import org.metafacture.framework.StreamReceiver;
21+
import org.metafacture.framework.XmlReceiver;
22+
import org.metafacture.framework.annotations.Description;
23+
import org.metafacture.framework.annotations.In;
24+
import org.metafacture.framework.annotations.Out;
25+
import org.metafacture.framework.helpers.DefaultXmlPipe;
26+
27+
import org.xml.sax.Attributes;
28+
import org.xml.sax.SAXException;
29+
30+
import java.text.Normalizer;
31+
32+
/**
33+
* A pica ppxml handler.
34+
*
35+
* @author Pascal Christoph (dr0i)
36+
*
37+
*/
38+
@Description("A pica ppxml reader")
39+
@In(XmlReceiver.class)
40+
@Out(StreamReceiver.class)
41+
@FluxCommand("handle-ppxml")
42+
public final class PpXmlHandler extends DefaultXmlPipe<StreamReceiver> {
43+
44+
private static final String SUBFIELD = "subf";
45+
private static final String DATAFIELD = "tag";
46+
private static final String RECORD = "record";
47+
private static final String NAMESPACE =
48+
"http://www.oclcpica.org/xmlns/ppxml-1.0";
49+
private static final String LEADER = "global";
50+
private String currentTag = "";
51+
private StringBuilder builder = new StringBuilder();
52+
53+
/**
54+
* Creates an instance of {@link PpXmlHandler}.
55+
*/
56+
public PpXmlHandler() {
57+
}
58+
59+
@Override
60+
public void startElement(final String uri, final String localName,
61+
final String qName, final Attributes attributes) throws SAXException {
62+
if (SUBFIELD.equals(localName)) {
63+
builder = new StringBuilder();
64+
currentTag = attributes.getValue("id");
65+
}
66+
else if (DATAFIELD.equals(localName)) {
67+
final String id = attributes.getValue("id");
68+
final String occurence = attributes.getValue("occ");
69+
if (occurence.matches("[1-9]")) {
70+
getReceiver().startEntity(id + "/0" + occurence);
71+
}
72+
else if (occurence.isEmpty()) {
73+
getReceiver().startEntity(id);
74+
}
75+
else {
76+
getReceiver().startEntity(id + "/" + occurence);
77+
}
78+
}
79+
else if (RECORD.equals(localName) && NAMESPACE.equals(uri)) {
80+
getReceiver().startRecord("");
81+
}
82+
else if (LEADER.equals(localName)) {
83+
builder = new StringBuilder();
84+
currentTag = LEADER;
85+
}
86+
}
87+
88+
@Override
89+
public void endElement(final String uri, final String localName,
90+
final String qName) throws SAXException {
91+
if (SUBFIELD.equals(localName)) {
92+
getReceiver().literal(currentTag,
93+
Normalizer.normalize(builder.toString().trim(), Normalizer.Form.NFC));
94+
}
95+
else if (DATAFIELD.equals(localName)) {
96+
getReceiver().endEntity();
97+
}
98+
else if (RECORD.equals(localName) && NAMESPACE.equals(uri)) {
99+
getReceiver().endRecord();
100+
}
101+
}
102+
103+
@Override
104+
public void characters(final char[] chars, final int start, final int length)
105+
throws SAXException {
106+
builder.append(chars, start, length);
107+
}
108+
109+
}

metafacture-biblio/src/main/resources/flux-commands.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ decode-pica org.metafacture.biblio.pica.PicaDecoder
2222
encode-pica org.metafacture.biblio.pica.PicaEncoder
2323
remodel-pica-multiscript org.metafacture.biblio.pica.PicaMultiscriptRemodeler
2424
handle-picaxml org.metafacture.biblio.pica.PicaXmlHandler
25+
handle-ppxml org.metafacture.biblio.pica.PpXmlHandler
2526

2627
handle-mabxml org.metafacture.biblio.AlephMabXmlHandler
2728
handle-comarcxml org.metafacture.biblio.ComarcXmlHandler

0 commit comments

Comments
 (0)