summaryrefslogtreecommitdiffstats
path: root/src/translators/tellico_xml.cpp
blob: d1ad3c1a31acc04fedd7de9877b761be65ceef9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/***************************************************************************
    copyright            : (C) 2003-2006 by Robby Stephenson
    email                : robby@periapsis.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of version 2 of the GNU General Public License as  *
 *   published by the Free Software Foundation;                            *
 *                                                                         *
 ***************************************************************************/

#include "tellico_xml.h"

#include <libxml/parserInternals.h> // needed for IS_LETTER
#include <libxml/parser.h> // has to be before valid.h
#include <libxml/valid.h>

#include <tqregexp.h>

const TQString Tellico::XML::nsXSL = TQString::tqfromLatin1("http://www.w3.org/1999/XSL/Transform");
const TQString Tellico::XML::nsBibtexml = TQString::tqfromLatin1("http://bibtexml.sf.net/");
const TQString Tellico::XML::dtdBibtexml = TQString::tqfromLatin1("bibtexml.dtd");

/*
 * VERSION 2 added namespaces, changed to multiple elements,
 * and changed the "keywords" field to "keyword"
 *
 * VERSION 3 broke out the formatFlag, and changed NoComplete to AllowCompletion
 *
 * VERSION 4 added a bibtex-field name for Bibtex collections, element name was
 * changed to 'entry', field elements changed to 'field', and boolean fields are now "true"
 *
 * VERSION 5 moved the bibtex-field and any other extended field property to property elements
 * inside the field element, and added the image element.
 *
 * VERSION 6 added id, i18n attributes, and year, month, day elements in date fields with a calendar name
 * attribute.
 *
 * VERSION 7 changed the application name to Tellico, renamed unitTitle to entryTitle, and made the id permanent.
 *
 * VERSION 8 added loans and saved filters.
 *
 * VERSION 9 changed music collections to always have three columns by default, with title/artist/length and
 * added file catalog collection.
 *
 * VERSION 10 added the game board collection.
 */
const uint Tellico::XML::syntaxVersion = 10;
const TQString Tellico::XML::nsTellico = TQString::tqfromLatin1("http://periapsis.org/tellico/");

const TQString Tellico::XML::nsBookcase = TQString::tqfromLatin1("http://periapsis.org/bookcase/");
const TQString Tellico::XML::nsDublinCore = TQString::tqfromLatin1("http://purl.org/dc/elements/1.1/");
const TQString Tellico::XML::nsZing = TQString::tqfromLatin1("http://www.loc.gov/zing/srw/");
const TQString Tellico::XML::nsZingDiag = TQString::tqfromLatin1("http://www.loc.gov/zing/srw/diagnostic/");

TQString Tellico::XML::pubTellico(int version) {
 return TQString::tqfromLatin1("-//Robby Stephenson/DTD Tellico V%1.0//EN").tqarg(version);
}

TQString Tellico::XML::dtdTellico(int version) {
  return TQString::tqfromLatin1("http://periapsis.org/tellico/dtd/v%1/tellico.dtd").tqarg(version);
}

bool Tellico::XML::validXMLElementName(const TQString& name_) {
  return xmlValidateNameValue((xmlChar *)name_.utf8().data());
}

TQString Tellico::XML::elementName(const TQString& name_) {
  TQString name = name_;
  // change white space to dashes
  name.replace(TQRegExp(TQString::tqfromLatin1("\\s+")), TQString::tqfromLatin1("-"));
  // first cut, if it passes, we're done
  if(XML::validXMLElementName(name)) {
    return name;
  }

  // next check first characters IS_DIGIT is defined in libxml/vali.d
  for(uint i = 0; i < name.length() && (!IS_LETTER(name[i].tqunicode()) || name[i] == '_'); ++i) {
    name = name.mid(1);
  }
  if(name.isEmpty() || XML::validXMLElementName(name)) {
    return name; // empty names are handled later
  }

  // now brute-force it, one character at a time
  uint i = 0;
  while(i < name.length()) {
    if(!XML::validXMLElementName(name.left(i+1))) {
      name.remove(i, 1); // remember it's zero-indexed
    } else {
      // character is ok, increment i
      ++i;
    }
  }
  return name;
}