PostgreSQL Source Code: contrib/xml2/xpath.c Source File (original) (raw)

1

2

3

4

5

6

8

16

17

18

19#include <libxml/xpath.h>

20#include <libxml/tree.h>

21#include <libxml/xmlmemory.h>

22#include <libxml/xmlerror.h>

23#include <libxml/parserInternals.h>

24

26 .name = "xml2",

27 .version = PG_VERSION

28);

29

30

31

33

34

35

36typedef struct

37{

39 xmlXPathContextPtr ctxt;

40 xmlXPathObjectPtr res;

42

43

44

46 xmlChar *toptagname, xmlChar *septagname,

47 xmlChar *plainsep);

48

50 xmlChar *septag, xmlChar *plainsep);

51

53

56

58

59

60

61

62

63

64

65

68{

70

71

73

74

75

76

77 xmlInitParser();

78

79 return xmlerrcxt;

80}

81

82

83

84

86

89{

92 xmlChar *ts,

93 *tt;

94

96

97 tt = xmlEncodeSpecialChars(NULL, ts);

98

100

102

103 xmlFree(tt);

104

106}

107

108

109

110

111

112

113

114

115

116

117

118

119static xmlChar *

121 xmlChar *toptagname,

122 xmlChar *septagname,

123 xmlChar *plainsep)

124{

125 xmlBufferPtr buf;

126 xmlChar *result;

127 int i;

128

129 buf = xmlBufferCreate();

130

131 if ((toptagname != NULL) && (xmlStrlen(toptagname) > 0))

132 {

133 xmlBufferWriteChar(buf, "<");

134 xmlBufferWriteCHAR(buf, toptagname);

135 xmlBufferWriteChar(buf, ">");

136 }

137 if (nodeset != NULL)

138 {

139 for (i = 0; i < nodeset->nodeNr; i++)

140 {

141 if (plainsep != NULL)

142 {

143 xmlBufferWriteCHAR(buf,

144 xmlXPathCastNodeToString(nodeset->nodeTab[i]));

145

146

147 if (i < (nodeset->nodeNr) - 1)

148 xmlBufferWriteChar(buf, (char *) plainsep);

149 }

150 else

151 {

152 if ((septagname != NULL) && (xmlStrlen(septagname) > 0))

153 {

154 xmlBufferWriteChar(buf, "<");

155 xmlBufferWriteCHAR(buf, septagname);

156 xmlBufferWriteChar(buf, ">");

157 }

158 xmlNodeDump(buf,

159 nodeset->nodeTab[i]->doc,

160 nodeset->nodeTab[i],

161 1, 0);

162

163 if ((septagname != NULL) && (xmlStrlen(septagname) > 0))

164 {

165 xmlBufferWriteChar(buf, "</");

166 xmlBufferWriteCHAR(buf, septagname);

167 xmlBufferWriteChar(buf, ">");

168 }

169 }

170 }

171 }

172

173 if ((toptagname != NULL) && (xmlStrlen(toptagname) > 0))

174 {

175 xmlBufferWriteChar(buf, "</");

176 xmlBufferWriteCHAR(buf, toptagname);

177 xmlBufferWriteChar(buf, ">");

178 }

179 result = xmlStrdup(buf->content);

180 xmlBufferFree(buf);

181 return result;

182}

183

184

185

186

187

188static xmlChar *

190{

192}

193

194

195

196

197

198

199

201

204{

211 xmlXPathObjectPtr res;

213

215

217

219

221

223

224 if (xpres == NULL)

227}

228

229

230

231

232

234

237{

243 xmlXPathObjectPtr res;

245

247

249

251

253

255

256 if (xpres == NULL)

259}

260

261

263

266{

272 xmlXPathObjectPtr res;

274

276

277

278

279

280

281

282

283 xpath = (xmlChar *) palloc(pathsize + 9);

284 memcpy(xpath, "string(", 7);

286 xpath[pathsize + 7] = ')';

287 xpath[pathsize + 8] = '\0';

288

290

292

294

296

297 if (xpres == NULL)

300}

301

302

304

307{

312 xmlXPathObjectPtr res;

314

316

318

320

321 if (res == NULL)

323

324 fRes = xmlXPathCastToNumber(res);

325

327

328 if (xmlXPathIsNaN(fRes))

330

332}

333

334

336

339{

343 int bRes;

344 xmlXPathObjectPtr res;

346

348

350

352

353 if (res == NULL)

355

356 bRes = xmlXPathCastToBoolean(res);

357

359

361}

362

363

364

365

366

367static xmlXPathObjectPtr

369{

372 xmlXPathCompExprPtr comppath;

373

374 workspace->doctree = NULL;

375 workspace->ctxt = NULL;

376 workspace->res = NULL;

377

379

381 {

383 docsize, NULL, NULL,

384 XML_PARSE_NOENT);

385 if (workspace->doctree != NULL)

386 {

387 workspace->ctxt = xmlXPathNewContext(workspace->doctree);

388 workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);

389

390

391 comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath);

392 if (comppath == NULL)

393 xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,

394 "XPath Syntax Error");

395

396

397 workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);

398

399 xmlXPathFreeCompExpr(comppath);

400 }

401 }

403 {

405

407

409 }

411

412 if (workspace->res == NULL)

414

416

417 return workspace->res;

418}

419

420

421static void

423{

424 if (workspace->res)

425 xmlXPathFreeObject(workspace->res);

426 workspace->res = NULL;

427 if (workspace->ctxt)

428 xmlXPathFreeContext(workspace->ctxt);

429 workspace->ctxt = NULL;

431 xmlFreeDoc(workspace->doctree);

432 workspace->doctree = NULL;

433}

434

437 xmlChar *toptag,

438 xmlChar *septag,

439 xmlChar *plainsep)

440{

441 xmlChar *xpresstr;

443

444 if (res == NULL)

445 return NULL;

446

447 switch (res->type)

448 {

449 case XPATH_NODESET:

451 toptag,

452 septag, plainsep);

453 break;

454

455 case XPATH_STRING:

456 xpresstr = xmlStrdup(res->stringval);

457 break;

458

459 default:

460 elog(NOTICE, "unsupported XQuery result: %d", res->type);

461 xpresstr = xmlStrdup((const xmlChar *) "");

462 }

463

464

466

467

468 xmlFree(xpresstr);

469

470 return xpres;

471}

472

473

474

475

476

478

481{

482

488

489

493

494

497

499 xmlChar **xpaths;

500 char *pos;

501 const char *pathsep = "|";

502

503 int numpaths;

504 int ret;

506 int j;

507 int rownr;

508

509 bool had_values;

512 volatile xmlDocPtr doctree = NULL;

513

515

516

519 (errcode(ERRCODE_SYNTAX_ERROR),

520 errmsg("xpath_table must have at least one output column")));

521

522

523

524

525

526

527

528

529

531

533 xpaths = (xmlChar **) palloc(rsinfo->setDesc->natts * sizeof(xmlChar *));

534

535

536

537

538

539

540 numpaths = 0;

541 pos = xpathset;

542 while (numpaths < (rsinfo->setDesc->natts - 1))

543 {

544 xpaths[numpaths++] = (xmlChar *) pos;

545 pos = strstr(pos, pathsep);

546 if (pos != NULL)

547 {

548 *pos = '\0';

549 pos++;

550 }

551 else

552 break;

553 }

554

555

557

558

559 appendStringInfo(&query_buf, "SELECT %s, %s FROM %s WHERE %s",

560 pkeyfield,

561 xmlfield,

563 condition);

564

566

568 elog(ERROR, "xpath_table: SPI execution failed for query %s",

569 query_buf.data);

570

573 spi_tupdesc = tuptable->tupdesc;

574

575

576

577

578

579

580 if (spi_tupdesc->natts != 2)

581 {

583 errmsg("expression returning multiple columns is not valid in parameter list"),

584 errdetail("Expected two columns in SPI result, got %d.", spi_tupdesc->natts)));

585 }

586

587

588

589

590

592

594 {

595

597

598 for (i = 0; i < proc; i++)

599 {

600 char *pkey;

601 char *xmldoc;

602 xmlXPathContextPtr ctxt;

603 xmlXPathObjectPtr res;

604 xmlChar *resstr;

605 xmlXPathCompExprPtr comppath;

607

608

609 spi_tuple = tuptable->vals[i];

610 pkey = SPI_getvalue(spi_tuple, spi_tupdesc, 1);

611 xmldoc = SPI_getvalue(spi_tuple, spi_tupdesc, 2);

612

613

614

615

616

617

620

621

623

624

625 if (xmldoc)

626 doctree = xmlReadMemory(xmldoc, strlen(xmldoc),

627 NULL, NULL,

628 XML_PARSE_NOENT);

629 else

630 doctree = NULL;

631

632 if (doctree == NULL)

633 {

634

638 }

639 else

640 {

641

642 rownr = 0;

643

644 do

645 {

646

647 had_values = false;

648 for (j = 0; j < numpaths; j++)

649 {

650 ctxt = xmlXPathNewContext(doctree);

651 ctxt->node = xmlDocGetRootElement(doctree);

652

653

654 comppath = xmlXPathCtxtCompile(ctxt, xpaths[j]);

655 if (comppath == NULL)

657 ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,

658 "XPath Syntax Error");

659

660

661 res = xmlXPathCompiledEval(comppath, ctxt);

662 xmlXPathFreeCompExpr(comppath);

663

664 if (res != NULL)

665 {

666 switch (res->type)

667 {

668 case XPATH_NODESET:

669

670 if (res->nodesetval != NULL &&

671 rownr < res->nodesetval->nodeNr)

672 {

673 resstr = xmlXPathCastNodeToString(res->nodesetval->nodeTab[rownr]);

674 had_values = true;

675 }

676 else

677 resstr = NULL;

678

679 break;

680

681 case XPATH_STRING:

682 resstr = xmlStrdup(res->stringval);

683 break;

684

685 default:

686 elog(NOTICE, "unsupported XQuery result: %d", res->type);

687 resstr = xmlStrdup((const xmlChar *) "");

688 }

689

690

691

692

693

694 values[j + 1] = (char *) resstr;

695 }

696 xmlXPathFreeContext(ctxt);

697 }

698

699

700 if (had_values)

701 {

705 }

706

707 rownr++;

708 } while (had_values);

709 }

710

711 if (doctree != NULL)

712 xmlFreeDoc(doctree);

713 doctree = NULL;

714

715 if (pkey)

717 if (xmldoc)

719 }

720 }

722 {

723 if (doctree != NULL)

724 xmlFreeDoc(doctree);

725

727

729 }

731

732 if (doctree != NULL)

733 xmlFreeDoc(doctree);

734

736

738

739

740

741

742

743

744

745

746 return (Datum) 0;

747}

static Datum values[MAXATTR]

int errdetail(const char *fmt,...)

int errcode(int sqlerrcode)

int errmsg(const char *fmt,...)

#define ereport(elevel,...)

HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)

AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)

#define PG_GETARG_TEXT_PP(n)

#define PG_RETURN_TEXT_P(x)

#define PG_RETURN_FLOAT4(x)

#define PG_RETURN_BOOL(x)

void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)

#define MAT_SRF_USE_EXPECTED_DESC

void heap_freetuple(HeapTuple htup)

void pfree(void *pointer)

SPITupleTable * SPI_tuptable

int SPI_exec(const char *src, long tcount)

char * SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)

void appendStringInfo(StringInfo str, const char *fmt,...)

void initStringInfo(StringInfo str)

Tuplestorestate * setResult

void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)

#define VARSIZE_ANY_EXHDR(PTR)

text * cstring_to_text(const char *s)

char * text_to_cstring(const text *t)

Datum xpath(PG_FUNCTION_ARGS)

struct PgXmlErrorContext PgXmlErrorContext

PgXmlErrorContext * pg_xml_init(PgXmlStrictness strictness)

void xml_ereport(PgXmlErrorContext *errcxt, int level, int sqlcode, const char *msg)

void pg_xml_done(PgXmlErrorContext *errcxt, bool isError)

@ PG_XML_STRICTNESS_LEGACY

static text * pgxml_result_to_text(xmlXPathObjectPtr res, xmlChar *toptag, xmlChar *septag, xmlChar *plainsep)

Datum xpath_bool(PG_FUNCTION_ARGS)

Datum xpath_number(PG_FUNCTION_ARGS)

Datum xpath_table(PG_FUNCTION_ARGS)

static xmlXPathObjectPtr pgxml_xpath(text *document, xmlChar *xpath, xpath_workspace *workspace)

static xmlChar * pgxml_texttoxmlchar(text *textstring)

PgXmlErrorContext * pgxml_parser_init(PgXmlStrictness strictness)

Datum xpath_string(PG_FUNCTION_ARGS)

static void cleanup_workspace(xpath_workspace *workspace)

Datum xml_encode_special_chars(PG_FUNCTION_ARGS)

Datum xpath_list(PG_FUNCTION_ARGS)

static xmlChar * pgxmlNodeSetToText(xmlNodeSetPtr nodeset, xmlChar *toptagname, xmlChar *septagname, xmlChar *plainsep)

PG_MODULE_MAGIC_EXT(.name="xml2",.version=PG_VERSION)

Datum xpath_nodeset(PG_FUNCTION_ARGS)

PG_FUNCTION_INFO_V1(xml_encode_special_chars)