PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ parse_marc21()

static LWGEOM * parse_marc21 ( xmlNodePtr  xnode)
static

MARC21/XML documents must have <record> as top level element. https://www.loc.gov/standards/marcxml/xml/spy/spy.html

If the coordinates are given in terms of a center point rather than outside limits, the longitude and latitude which form the central axis are recorded twice (in subfields $d and $e and in $f and $g, respectively).

MARC21/XML Document has a <record> but no <datafield:034>

Definition at line 384 of file lwgeom_in_marc21.c.

384 {
385
386 int ngeoms;
387 int i;
388 xmlNodePtr datafield;
389 xmlNodePtr subfield;
390 LWGEOM *result;
391 LWGEOM **lwgeoms = (LWGEOM**) lwalloc(sizeof(LWGEOM*));
392 uint8_t geometry_type;
393 uint8_t result_type;
394 char *code;
395 char *literal;
396
397 POSTGIS_DEBUGF(2, "parse_marc21 called: root '<%s>'", xnode->name);
398
404 if (!is_xml_element(xnode, "record"))
405 lwpgerror("invalid MARC21/XML document. Root element <record> expected but <%s> found.",xnode->name);
406
407 result_type = 0;
408 ngeoms = 0;
409
410 for (datafield = xnode->children; datafield != NULL; datafield = datafield->next) {
411
412 char *lw = NULL;
413 char *le = NULL;
414 char *ln = NULL;
415 char *ls = NULL;
416
417 if (datafield->type != XML_ELEMENT_NODE) continue;
418
419 if (!is_xml_element(datafield, "datafield") || xmlStrcmp(xmlGetProp(datafield, (xmlChar*) "tag"),(xmlChar*) "034") != 0) continue;
420
421 POSTGIS_DEBUG(3, " datafield found");
422
423 for (subfield = datafield->children; subfield != NULL; subfield = subfield->next) {
424
425 if (subfield->type != XML_ELEMENT_NODE) continue;
426 if (!is_xml_element(subfield, "subfield"))
427 continue;
428
429 code = (char*) xmlGetProp(subfield, (xmlChar*) "code");
430
431 if ((strcmp(code, "d") != 0 &&
432 strcmp(code, "e") != 0 &&
433 strcmp(code, "f") != 0 &&
434 strcmp(code, "g")) != 0)
435 continue;
436
437 literal = (char*) xmlNodeGetContent(subfield);
438
439 POSTGIS_DEBUGF(3, " subfield code '%s': %s", code, literal);
440
441 if (is_literal_valid(literal) == LW_TRUE) {
442
443 if (strcmp(code, "d") == 0) lw = literal;
444 else if (strcmp(code, "e") == 0) le = literal;
445 else if (strcmp(code, "f") == 0) ln = literal;
446 else if (strcmp(code, "g") == 0) ls = literal;
447
448 } else {
449
450 lwpgerror("parse error - invalid literal at 034$%s: \"%s\"", code, literal);
451
452 }
453
454 }
455
456 xmlFreeNode(subfield);
457
458 if (lw && le && ln && ls) {
459
460 double w = parse_geo_literal(lw);
461 double e = parse_geo_literal(le);
462 double n = parse_geo_literal(ln);
463 double s = parse_geo_literal(ls);
464 geometry_type = 0;
465
466 if (ngeoms > 0) lwgeoms = (LWGEOM**)
467 lwrealloc(lwgeoms, sizeof(LWGEOM*) * (ngeoms + 1));
468
469 if (fabs(w - e) < 0.0000001f && fabs(n - s) < 0.0000001f) {
470
477 lwgeoms[ngeoms] = (LWGEOM*) lwpoint_make2d(SRID_UNKNOWN, w, s);
478 geometry_type = MULTIPOINTTYPE;
479
480 } else {
481
482 lwgeoms[ngeoms] = (LWGEOM*) lwpoly_construct_envelope(SRID_UNKNOWN, w, n, e, s);
483 geometry_type = MULTIPOLYGONTYPE;
484
485 }
486
487 if (ngeoms && result_type != geometry_type) {
488 result_type = COLLECTIONTYPE;
489 } else {
490 result_type = geometry_type;
491 }
492
493 ngeoms++;
494
495 } else {
496
497 if (lw || le || ln || ls) {
498
499 lwpgerror("parse error - the Coded Cartographic Mathematical Data (datafield:034) in the given MARC21/XML is incomplete. Coordinates for subfields \"$d\",\"$e\",\"$f\" and \"$g\" are expected.");
500 }
501
502 }
503
504 }
505
506 POSTGIS_DEBUG(5, " xmlFreeNode(datafield)");
507 xmlFreeNode(datafield);
508
509 if (ngeoms == 1) {
510
511 POSTGIS_DEBUGF(2, "=> parse_marc21 returns single geometry: %s",lwtype_name(lwgeom_get_type(lwgeoms[0])));
512 lwgeom_force_clockwise(lwgeoms[0]);
513 return lwgeoms[0];
514
515 } else if (ngeoms > 1) {
516
518
519 for (i = 0; i < ngeoms; i++) {
520
521 POSTGIS_DEBUGF(3, " adding geometry to result set: %s",lwtype_name(lwgeom_get_type(lwgeoms[i])));
522 lwgeom_force_clockwise(lwgeoms[i]);
524
525 }
526
527 POSTGIS_DEBUGF(2, "=> parse_marc21 returns a collection: %s", lwtype_name(lwgeom_get_type(result)));
528 return result;
529
530 }
531
535 POSTGIS_DEBUG(2, "=> parse_marc21 returns NULL");
536 return NULL;
537
538}
char * s
Definition cu_in_wkt.c:23
static char * w
Definition cu_out_twkb.c:25
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition cu_print.c:267
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
#define COLLECTIONTYPE
Definition liblwgeom.h:108
void * lwrealloc(void *mem, size_t size)
Definition lwutil.c:242
#define MULTIPOINTTYPE
Definition liblwgeom.h:105
LWPOLY * lwpoly_construct_envelope(int32_t srid, double x1, double y1, double x2, double y2)
Definition lwpoly.c:98
void * lwalloc(size_t size)
Definition lwutil.c:227
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:107
LWPOINT * lwpoint_make2d(int32_t srid, double x, double y)
Definition lwpoint.c:163
void lwgeom_force_clockwise(LWGEOM *lwgeom)
Definition lwgeom.c:73
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:93
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:215
static bool is_xml_element(xmlNodePtr xn, const char *xml_name)
static double parse_geo_literal(char *literal)
static int is_literal_valid(const char *literal)
static uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Definition lwinline.h:141

References COLLECTIONTYPE, is_literal_valid(), is_xml_element(), LW_TRUE, lwalloc(), lwcollection_add_lwgeom(), lwcollection_construct_empty(), lwgeom_force_clockwise(), lwgeom_get_type(), lwpoint_make2d(), lwpoly_construct_envelope(), lwrealloc(), lwtype_name(), MULTIPOINTTYPE, MULTIPOLYGONTYPE, parse_geo_literal(), result, s, SRID_UNKNOWN, and w.

Referenced by ST_GeomFromMARC21().

Here is the call graph for this function:
Here is the caller graph for this function: