3require_once
"ISO2709.php";
7 parent::__construct(
$input );
8 $this->prepend = fread( $this->input, 5 );
10 else if( $this->prepend ===
"=LDR " ) {
11 $this->RecordTerminator =
"\r\n\r\n";
12 }
else if( $this->prepend ===
"=000 " ) {
13 $this->RecordTerminator =
"\r\n\r\n";
15 $this->recordClass =
"MARC21Record";
21 parent::__construct(
$input );
22 $this->recordClass =
"MARC21Record";
29 parent::__construct();
33 $this->
set_default(
"lengthOfStartingCharacterPosition", 5 );
34 $this->
set_default(
"lengthOfImplementationDefined", 0 );
35 $this->mnemonicType =
"LC";
39 return is_string( $tag ) and ctype_digit( $tag ) and strlen( $tag ) == 3 and $tag !==
"000";
43 if( !self::isTagValid( $tag ) ) {
44 $this->
exception(
"MARC21: Tags must be numeric and must be 3 bytes long. Thus '$tag' is not allowed.");
47 return parent::assertTagValid( $tag );
51 return $tag !=
"001" and $tag !=
"005";
56 if(!parent::isTagValid($a) || !parent::isTagValid($b))
return 0;
57 if( $a === $b )
return 0;
58 $a0 = substr( $a, 0, 2 );
59 $b0 = substr( $b, 0, 2 );
60 if( $a0 === $b0 and $a0 ===
"00" )
return strcmp( $a, $b );
61 if( $a0 ===
"00" ) {
return -1; }
62 if( $b0 ===
"00" ) {
return 1; }
63 $a0 = substr( $a, 0, 1 );
64 $b0 = substr( $b, 0, 1 );
65 if( $a0 ===
"0" and $b0 ===
"0" ) {
66 if( $a ===
"049" )
return 1;
67 if( $b ===
"049" )
return -1;
69 return strcmp( $a0, $b0 );
73 if( self::tagOrder( $a, $b ) > 0 ) {
74 $this->
exception(
"MARC21: 00* is ordered by ASCII, and the rest by century. Thus '$a' should not precede '$b'.");
77 return parent::assertTagOrder( $a, $b );
81 $ret = parent::loadFromBinaryString( $string );
82 if( $ret ===
false )
return $ret;
83 if( strlen($this->leader) != 24 )
return false;
84 if(!ctype_print($this->leader))
85 $this->
exception(
"MARC21: Leader can only contain 0x20 through 0x7E, not 0x" . bin2hex( $this->leader ) );
86 if($this->leader[23] !=
"0")
87 $this->
exception(
"MARC21: Last character of leader is supposed to be '0' not '{$this->leader[23]}'");
91 # 00*-00* are in numeric-alpha order in both directory and data (with no intervening in either directory or data)
95 parent::CheckField( $field );
96 if( substr( $field->tag, 0, 2 ) ===
"00" ) {
100 if( !preg_match(
"/^[0-9a-z ]{2}$/", $field->indicators) )
101 $this->
exception(
"MARC21 8.3.5: indicators should be length 2, and each character should be lower case, numeric, or a space. " .
102 "So field '{$field->tag}' with indicators '{$field->indicators}' is not allowed." );
104 foreach( $field->subfields as $subfield ) {
105 if( !preg_match(
"/^[0-9a-z]$/", $subfield->identifier) )
106 $this->
exception(
"MARC21 8.3.5: subfield identifiers should be length 1, and each character should be lower case or numeric. " .
107 "So field '{$field->tag}' with subfield '{$subfield->identifier}' is not allowed." );
113 $this->leader = array();
114 $this->fields = array();
115 $this->exceptions = array();
116 $this->raw = $string;
117 foreach( explode(
"\r\n", $string ) as $line ) {
119 if( $field !==
false ) $this->
AppendField( $field );
124 $this->leader = array(); # XXX ??
125 $this->fields = array();
126 $this->exceptions = array();
127 $this->raw = $string;
129 $doc =
new DOMDocument();
130 $doc->loadXML($string);
131 $xpath =
new DOMXpath($doc);
133 $leaderfield = $xpath->query(
'//record/leader');
134 if ($leaderfield) { # <leader>00838mas a2200301 a 4500</leader>
135 $leader = $leaderfield[0]->nodeValue;
136 if( strlen(
$leader) != 24 )
return false;
140 # $field = new ISO2709Field( $tag, $data, $indicators, $subfields, $directoryEntry, $this );
142 $controlfield = $xpath->query(
'//record/controlfield');
143 if ($controlfield) { # <controlfield tag=
"001"> 92005291 </controlfield>
144 foreach ($controlfield as $cfd) {
145 $tag = $cfd->getAttribute(
'tag');
146 $data = $cfd->nodeValue;
152 $datafield = $xpath->query(
'//record/datafield');
153 if ($datafield) { # <datafield ind1=
" " ind2=
" " tag=
"035"><subfield code=
"9">AHE8121LM</subfield></datafield>
154 foreach ($datafield as $dfd) {
155 $tag = $dfd->getAttribute(
'tag');
156 $indicators = $dfd->getAttribute(
'ind1') . $dfd->getAttribute(
'ind2');
157 $subfields = array();
158 foreach ($dfd->childNodes as $subf) {
159 if ($subf->nodeType ==
'1') { # Element
160 $code = $subf->getAttribute(
'code');
161 $value = $subf->nodeValue;
165 $field =
new ISO2709Field( $tag,
null, $indicators, $subfields);
173 $str .=
'<leader>' . $this->leader .
'</leader>';
174 foreach( $this->fields as $field ) {
176 if ( isset($field->data ) ) {
178 $str .=
"<controlfield tag=\"$tag\">$data</controlfield>";
182 $str .=
"<datafield tag=\"$tag\" ind1=\"$ind1\" ind2=\"$ind2\">";
183 foreach( $field->subfields as $subfield ) {
186 $str .=
"<subfield code=\"$code\">$data</subfield>";
188 $str .=
'</datafield>';
192 file_put_contents(
"/tmp/wiggle",$str);
197 if (preg_match(
"/^ *([^ ])/",$string,$m)) {
198 $starts_with = $m[1];
199 if ($starts_with ==
'<') {
202 if ($starts_with ==
'=') {
205 if (ctype_digit($starts_with)) {
214 $equ = substr( $line, 0, 1 );
215 $tag = substr( $line, 1, 3 );
216 $spa = substr( $line, 4, 2 );
217 $dat = substr( $line, 6 );
218 if( $equ !==
"=" or $spa !==
" " ) {
219 $this->
exception(
"Mnemonic: unreadable line '$line'");
222 if( $tag ==
"LDR" or $tag ==
"000" ) {
223 $this->leader = $dat;
224 $this->indicatorLength = 2;
225 $this->identifierLength = 2;
226 $this->mnemonicType = ($tag ==
"LDR") ?
"TRME" :
"LCMB";
229 if( $this->mnemonicType ===
"TRME" ) {
231 $dat = str_replace(
'\\',
' ', $dat );
232 }
else if( $this->mnemonicType ===
"LCMB" ) {
234 $dat = str_replace(
'#',
' ', $dat );
246 if( substr($tag,0,2) ===
"00" ) {
247 $dat = str_replace(
'#',
' ', $dat );
248 $dat = str_replace(
'\\',
' ', $dat );
250 if( $dat[0] ==
'\\' ) $dat[0] =
' ';
251 if( $dat[1] ==
'\\' ) $dat[1] =
' ';
252 if( $dat[0] ==
'#' ) $dat[0] =
' ';
253 if( $dat[1] ==
'#' ) $dat[1] =
' ';
263 if( is_string( $field ) ) {
266 if( is_a( $field,
"ISO2709Field" ) )
return parent::AppendField( $field, $reorder );
270 function AsMnemonicString( $leader_tag =
'LDR', $field_initiator =
'=', $tag_terminator =
' ', $identifier_initiator =
'$', $field_terminator =
"\r\n", $record_terminator =
"\r\n", $space_replacer =
' ') {
271 if( $this->mnemonicType ===
"TRME" )
return parent::AsMnemonicString(
"LDR",
"=",
" ",
"\$",
"\r\n",
"\r\n",
"\\" );
272 if( $this->mnemonicType ===
"LCMB" )
return parent::AsMnemonicString(
"000",
"=",
" ",
"\$",
"\r\n",
"\r\n",
"#" );
273 if( $this->mnemonicType ===
"VGER" )
return parent::AsMnemonicString(
"LEADER",
"=",
" ",
"|",
"\r\n",
"\r\n",
"#" );
274 #return parent::AsMnemonicString( "LDR", "=", " ", "\$", "\r\n", "\r\n", " " );
275 return parent::AsMnemonicString( $leader_tag, $field_initiator, $tag_terminator, $identifier_initiator, $field_terminator, $record_terminator, $space_replacer );
279 foreach( $this->fields as $k => $v ) {
280 $vmne = $v->AsMnemonicString(
"=",
" ",
"\$",
"\r\n",
'\\' );
281 if( preg_match(
"@^" . $pattern .
"@", $vmne ) ) unset( $this->fields[$k] );
283 $this->fields = array_values( $this->fields );
289 return htmlspecialchars($str, ENT_XML1 | ENT_COMPAT,
'UTF-8');
293 return htmlspecialchars($str, ENT_XML1,
'UTF-8');
set_default( $name, $value)
ParseBinaryField( $tag, $data, $directoryEntry)
loadFromXMLString( $string)
ParseMnemonicLine( $line)
AsMnemonicString( $leader_tag='LDR', $field_initiator='=', $tag_terminator=' ', $identifier_initiator='$', $field_terminator="\r\n", $record_terminator="\r\n", $space_replacer=' ')
AppendField( $field, $reorder=false)
loadFromMnemonicString( $string)
loadFromBinaryString( $string, $fuzzy=true)