marc xpath parser and compiler. needs more testing
[Evergreen.git] / Open-ILS / web / js / dojo / openils / MarcXPathParser.js
1 /* ---------------------------------------------------------------------------
2  * Copyright (C) 2008  Georgia Public Library Service
3  * Bill Erickson <erickson@esilibrary.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * ---------------------------------------------------------------------------
15  */
16
17 if(!dojo._hasResource["openils.MarcXPathParser"]) {
18     dojo._hasResource["openils.MarcXPathParser"] = true;
19     dojo.provide("openils.MarcXPathParser");
20
21     dojo.declare('openils.MarcXPathParser', null, {
22         /**
23           * Parse a marc xpath expression and return the breakdown of tags, subfields, and match offset
24           */
25         parse : function(expr) {
26             // this is about as simple as it gets. will need more 
27             // smarts if the expressions get more complicated
28             var tags = expr.match(/\d{3}/g);
29             var subfields = expr.match(/['"]([a-z]+)['"]/);
30             var offset = expr.match(/\[(\d+)\]$/);
31             return {
32                 tags : tags,
33                 subfields : (subfields) ? subfields[1].split('') : [],
34                 offset : (offset) ? offset[1] : null
35             }
36         },
37
38         /**
39           * Creates an XPath expression from a set of tags/subfields/offset
40           */
41         compile : function(parts) {
42             var str = '//*[';
43             for(var i = 0; i < parts.tags.length; i++) {
44                 var tag = parts.tags[i];
45                 if(i > 0)
46                     str += ' or ';
47                 str += '@tag="'+tag+'"';
48             }
49             str += ']';
50             if(parts.subfields.length > 0) {
51                 str += '/*[';
52                 if(parts.subfields.length == 1) {
53                     str += '@code="' + parts.subfields[0] + '"]';
54                 } else {
55                     str += 'contains("' + parts.subfields.join('') +'",@code)]';
56                 }
57             }
58             if(parts.offset)
59                 str += '[' + parts.offset + ']';
60             return str;
61         }
62     });
63 }
64
65
66 openils.MarcXPathParser.test = function() {
67     var expr = [
68         '//*[@tag="300"]/*[@code="a"][1]',
69         '//*[@tag="020"]/*[@code="a"]',
70         '//*[@tag="022"]/*[@code="a"]',
71         '//*[@tag="020" or @tag="022"]/*[@code="c"][1]',
72         '//*[@tag="001"]',
73         '//*[@tag="901"]/*[@code="a"]',
74         '//*[@tag="901"]/*[@code="b"]',
75         '//*[@tag="901"]/*[@code="c"]',
76         '//*[@tag="260"]/*[@code="b"][1]',
77         '//*[@tag="250"]/*[@code="a"][1]',
78         '//*[@tag="245"]/*[contains("abcmnopr",@code)]',
79         '//*[@tag="260"]/*[@code="c"][1]',
80         '//*[@tag="100" or @tag="110" or @tag="113"]/*[contains("ad",@code)]',
81         '//*[@tag="240"]/*[@code="l"][1]'
82     ];
83
84     var parser = new openils.MarcXPathParser();
85
86     for(var i = 0; i < expr.length; i++) {
87         var vals = parser.parse(expr[i]);
88         console.log(expr[i]);
89         console.log(vals.tags);
90         console.log(vals.subfields);
91         console.log(vals.offset);
92         console.log(parser.compile(vals));
93     }
94 };
95