root/lu/LUXMLInputStream.lua

Revision 814 (checked in by rsz, 3 years ago)

cleanup

Line 
1 --------------------------------------------------------------------------------
2 -- Title:               LUXMLInputStream.lua
3 -- Description:         Like a square peg in a round hole
4 -- Author:              Raphaël Szwarc http://alt.textdrive.com/lua/
5 -- Creation Date:       February 1, 2005
6 -- Legal:               Copyright (C) 2005 Raphaël Szwarc
7 --------------------------------------------------------------------------------
8
9 -- import dependencies
10 local LUInputStream = require( "LUInputStream" )
11 local LUBundle = require( "LUBundle" )
12 local LUMap = require( "LUMap" )
13 local LUString = require( "LUString" )
14 local string = require( "string" )
15
16 -- define the class
17 local super = LUInputStream
18 local self = super()
19
20 -- class variable(s)
21 local _entities = nil
22
23 -- constant(s)
24 self.Tag = 1
25 self.EndTag = 2
26 self.Text = 3
27
28 -- initialization method
29 function self:init( aContent, anIndex, aLength )
30         self = super.init( self, aContent, anIndex, aLength )
31        
32         self._type = self.Tag
33        
34         return self
35 end
36
37 -- method to read a tag
38 function self:read()
39         local aContent = self:content()
40         local anIndex = self:index()
41        
42         if self._type ~= self.Text then
43                 local aStart = aContent:find( "%b<>", anIndex )
44                
45                 if aStart == nil then
46                         aStart = self:length() + 1
47                 end
48                
49                 if aStart ~= nil then
50                         local aText = aContent:sub( anIndex, aStart - 1 )
51                        
52                         aText = LUString:trim( aText )
53                        
54                         if aText:len() > 0 then
55                                 aText = self:decode( aText )
56                        
57                                 self:setIndex( aStart - 1 )
58                                
59                                 self._type = self.Text
60                                
61                                 return self.Text, aText
62                         end
63                 end
64         end
65
66         do
67                 local aStart, anEnd = aContent:find( "%b<>", anIndex )
68                
69                 if aStart ~= nil then
70                         local aTag = aContent:sub( aStart, anEnd )
71                         local someAttributes = nil
72                         local aFunction = function ( aKey, _, aValue )
73                                 someAttributes = someAttributes or LUMap()
74                                 someAttributes:put( aKey:lower(), self:decode( aValue ) )
75                         end
76                         local aNameIndex = aTag:find( "[%c%s]+" ) or aTag:len() - 1
77                         local aName = aTag:sub( 2, aNameIndex ):lower()
78
79                         aName = LUString:trim( aName )
80                         aName = aName:gsub( "/+$", "" )
81
82                         self:setIndex( anEnd + 1 )
83                        
84                         -- as per http://lua-users.org/wiki/LuaXml
85                         aTag:gsub( "(%w+)=([\"'])(.-)%2", aFunction )
86
87                         if aName:sub( 1, 1 ) == "/" then
88                                 aName = aName:sub( 2, aName:len() )
89                                
90                                 self._type = self.EndTag
91
92                                 return self.EndTag, aTag, aName, someAttributes
93                         else
94                                 self._type = self.Tag
95
96                                 return self.Tag, aTag, aName, someAttributes
97                         end
98                 end
99         end
100
101         return nil
102 end
103
104 -- method to read a text
105 function self:readChar()
106         while true do
107                 local aType, aContent, aName, someAttributes = self:read()
108                
109                 if aType == self.Text then
110                         return aContent
111                 elseif aType == nil then
112                         break
113                 end
114         end
115        
116         return nil
117 end
118
119 -- private method to decode a given entity
120 local function CharWithEntity( aSymbol, anEntity )
121         if aSymbol == "#" then
122                 local aCode = tonumber( ( anEntity:gsub( "^x", "0x" ) ) )
123
124                 if aCode ~= nil and aCode < 256 then
125                         return string.char( aCode )
126                 end
127         else
128                 local aValue = self:entities():get( anEntity )
129
130                 if aValue ~= nil then
131                         return aValue
132                 end
133         end
134        
135         return ( "&%s%s;" ):format( aSymbol, anEntity )
136 end
137
138 -- method to decode a given string
139 function self:decode( aString )
140         if aString ~= nil then
141                 aString = aString:gsub( "&(#?)(%w+);", CharWithEntity ) 
142         end
143        
144         return aString
145 end
146
147 -- method to access the entities
148 function self:entities()
149         if _entities == nil then
150                 local aBundle = LUBundle:bundleWithName( "LUXMLInputStream" )
151                 local aFile = aBundle:fileWithName( "LUXMLInputStream", "txt" )
152
153                 _entities = LUMap():load( aFile )
154         end
155        
156         return _entities
157 end
158
159 return self
Note: See TracBrowser for help on using the browser.