elementparser.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Copyright (C) 2010 Søren Roug, European Environment Agency
  4. #
  5. # This is free software. You may redistribute it under the terms
  6. # of the Apache license and the GNU General Public License Version
  7. # 2 or at your option any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public
  15. # License along with this program; if not, write to the Free Software
  16. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. #
  18. # Contributor(s):
  19. #
  20. import unittest
  21. """ Really simplistic parser of an element with attributes """
  22. class ElementParser:
  23. def __init__(self, s, elmttoparse):
  24. qelements = s.split('<')
  25. for i in range(len(qelements)):
  26. q = qelements[i]
  27. if q[:len(elmttoparse)] == elmttoparse:
  28. s = '<'.join([''] + qelements[i:])
  29. self.attributes = {}
  30. self.element = None
  31. currattr = None
  32. buf = []
  33. START = 1
  34. INELEM = 2
  35. SPACE = 3
  36. INATTR = 4
  37. INVALUE=5
  38. BEFOREVALUE = 6
  39. NOMORE = 7
  40. state=START
  41. ls = list(s)
  42. for c in ls:
  43. if state == NOMORE:
  44. continue
  45. if state == INVALUE: # We're in the value of the attribute. Only look for the terminator
  46. if c == '"':
  47. state = SPACE
  48. c = ''.join(buf)
  49. self.attributes[currattr] = c
  50. buf = []
  51. else:
  52. buf.append(c)
  53. else:
  54. if c == '<':
  55. state = INELEM
  56. elif c == ' ':
  57. if state == INELEM:
  58. self.element = ''.join(buf)
  59. buf = []
  60. state = SPACE
  61. elif c == '=':
  62. if state == INATTR:
  63. state = BEFOREVALUE
  64. currattr = ''.join(buf)
  65. buf = []
  66. elif c == '"':
  67. state = INVALUE
  68. elif c == '>' or c == '/':
  69. state = NOMORE
  70. elif c > '"' and c <= 'z' and state == SPACE: # Start of attribute
  71. state = INATTR
  72. buf = []
  73. buf.append(c)
  74. else:
  75. buf.append(c)
  76. def has_value(self, attribute, value):
  77. v = self.attributes.get(attribute, None)
  78. if v and v == value: return True
  79. return False
  80. class TestParser(unittest.TestCase):
  81. def test1(self):
  82. s='<draw:object xlink:href="./Object 1"/><style:style style:name="Standard" style:display-name="Standard" style:family="paragraph"><style:property/>'
  83. e = ElementParser(s,'style:style')
  84. self.assertEqual(e.element,'style:style')
  85. assert e.has_value("style:display-name","Standard")
  86. e = ElementParser(s,'draw:object')
  87. self.assertEqual(e.element,'draw:object')
  88. assert e.has_value("xlink:href","./Object 1")
  89. if __name__ == '__main__':
  90. unittest.main()