390 lines
8.2 KiB
Lua
390 lines
8.2 KiB
Lua
local xml = require 'pl.xml'
|
|
local asserteq = require 'pl.test'.asserteq
|
|
local dump = require 'pl.pretty'.dump
|
|
|
|
-- Prosody stanza.lua style XML building
|
|
|
|
d = xml.new 'top' : addtag 'child' : text 'alice' : up() : addtag 'child' : text 'bob'
|
|
|
|
d = xml.new 'children' :
|
|
addtag 'child' :
|
|
addtag 'name' : text 'alice' : up() : addtag 'age' : text '5' : up() : addtag('toy',{type='fluffy'}) : up() :
|
|
up() :
|
|
addtag 'child':
|
|
addtag 'name' : text 'bob' : up() : addtag 'age' : text '6' : up() : addtag('toy',{type='squeaky'})
|
|
|
|
asserteq(
|
|
xml.tostring(d,'',' '),
|
|
[[
|
|
|
|
<children>
|
|
<child>
|
|
<name>alice</name>
|
|
<age>5</age>
|
|
<toy type='fluffy'/>
|
|
</child>
|
|
<child>
|
|
<name>bob</name>
|
|
<age>6</age>
|
|
<toy type='squeaky'/>
|
|
</child>
|
|
</children>]])
|
|
|
|
-- Orbit-style 'xmlification'
|
|
|
|
local children,child,toy,name,age = xml.tags 'children, child, toy, name, age'
|
|
|
|
d1 = children {
|
|
child {name 'alice', age '5', toy {type='fluffy'}},
|
|
child {name 'bob', age '6', toy {type='squeaky'}}
|
|
}
|
|
|
|
assert(xml.compare(d,d1))
|
|
|
|
-- or we can use a template document to convert Lua data to LOM
|
|
|
|
templ = child {name '$name', age '$age', toy{type='$toy'}}
|
|
|
|
d2 = children(templ:subst{
|
|
{name='alice',age='5',toy='fluffy'},
|
|
{name='bob',age='6',toy='squeaky'}
|
|
})
|
|
|
|
assert(xml.compare(d1,d2))
|
|
|
|
-- Parsing Google Weather service results --
|
|
|
|
local joburg = [[
|
|
<xml_api_reply version='1'>
|
|
<weather module_id='0' tab_id='0' mobile_zipped='1' section='0' row='0' mobile_row='0'>
|
|
<forecast_information>
|
|
<city data='Johannesburg, Gauteng'/>
|
|
<postal_code data='Johannesburg,ZA'/>
|
|
<latitude_e6 data=''/>
|
|
<longitude_e6 data=''/>
|
|
<forecast_date data='2010-10-02'/>
|
|
<current_date_time data='2010-10-02 18:30:00 +0000'/>
|
|
<unit_system data='US'/>
|
|
</forecast_information>
|
|
<current_conditions>
|
|
<condition data='Clear'/>
|
|
<temp_f data='75'/>
|
|
<temp_c data='24'/>
|
|
<humidity data='Humidity: 19%'/>
|
|
<icon data='/ig/images/weather/sunny.gif'/>
|
|
<wind_condition data='Wind: NW at 7 mph'/>
|
|
</current_conditions>
|
|
<forecast_conditions>
|
|
<day_of_week data='Sat'/>
|
|
<low data='60'/>
|
|
<high data='89'/>
|
|
<icon data='/ig/images/weather/sunny.gif'/>
|
|
<condition data='Clear'/>
|
|
</forecast_conditions>
|
|
<forecast_conditions>
|
|
<day_of_week data='Sun'/>
|
|
<low data='53'/>
|
|
<high data='86'/>
|
|
<icon data='/ig/images/weather/sunny.gif'/>
|
|
<condition data='Clear'/>
|
|
</forecast_conditions>
|
|
<forecast_conditions>
|
|
<day_of_week data='Mon'/>
|
|
<low data='57'/>
|
|
<high data='87'/>
|
|
<icon data='/ig/images/weather/sunny.gif'/>
|
|
<condition data='Clear'/>
|
|
</forecast_conditions>
|
|
<forecast_conditions>
|
|
<day_of_week data='Tue'/>
|
|
<low data='60'/>
|
|
<high data='84'/>
|
|
<icon data='/ig/images/weather/sunny.gif'/>
|
|
<condition data='Clear'/>
|
|
</forecast_conditions>
|
|
</weather>
|
|
</xml_api_reply>
|
|
|
|
]]
|
|
|
|
local d = xml.parse(joburg)
|
|
|
|
function match(t,xpect)
|
|
local res,ret = d:match(t)
|
|
asserteq(res,xpect)
|
|
end
|
|
|
|
t1 = [[
|
|
<weather>
|
|
<current_conditions>
|
|
<condition data='$condition'/>
|
|
<temp_c data='$temp'/>
|
|
</current_conditions>
|
|
</weather>
|
|
]]
|
|
|
|
match(t1,{
|
|
condition = "Clear",
|
|
temp = "24",
|
|
} )
|
|
|
|
t2 = [[
|
|
<weather>
|
|
{{<forecast_conditions>
|
|
<day_of_week data='$day'/>
|
|
<low data='$low'/>
|
|
<high data='$high'/>
|
|
<condition data='$condition'/>
|
|
</forecast_conditions>}}
|
|
</weather>
|
|
]]
|
|
|
|
match(t2,{
|
|
{
|
|
low = "60",
|
|
high = "89",
|
|
day = "Sat",
|
|
condition = "Clear",
|
|
},
|
|
{
|
|
low = "53",
|
|
high = "86",
|
|
day = "Sun",
|
|
condition = "Clear",
|
|
},
|
|
{
|
|
low = "57",
|
|
high = "87",
|
|
day = "Mon",
|
|
condition = "Clear",
|
|
},
|
|
{
|
|
low = "60",
|
|
high = "84",
|
|
day = "Tue",
|
|
condition = "Clear",
|
|
}
|
|
})
|
|
|
|
config = [[
|
|
<config>
|
|
<alpha>1.3</alpha>
|
|
<beta>10</beta>
|
|
<name>bozo</name>
|
|
</config>
|
|
]]
|
|
d,err = xml.parse(config)
|
|
if not d then print(err); os.exit(1) end
|
|
|
|
|
|
-- can match against wildcard tag names (end with -)
|
|
-- can be names
|
|
match([[
|
|
<config>
|
|
{{<key->$value</key->}}
|
|
</config>
|
|
]],{
|
|
{key="alpha", value = "1.3"},
|
|
{key="beta", value = "10"},
|
|
{key="name",value = "bozo"},
|
|
})
|
|
|
|
-- can be numerical indices
|
|
match([[
|
|
<config>
|
|
{{<1->$2</1->}}
|
|
</config>
|
|
]],{
|
|
{"alpha","1.3"},
|
|
{"beta","10"},
|
|
{"name","bozo"},
|
|
})
|
|
|
|
-- _ is special; means 'this value is key of captured table'
|
|
match([[
|
|
<config>
|
|
{{<_->$1</_->}}
|
|
</config>
|
|
]],{
|
|
alpha = {"1.3"},
|
|
beta = {"10"},
|
|
name = {"bozo"},
|
|
})
|
|
|
|
-- the numerical index 0 is special: a capture of {[0]=val} becomes simply the value val
|
|
match([[
|
|
<config>
|
|
{{<_->$0</_->}}
|
|
</config>
|
|
]],{
|
|
alpha = "1.3",
|
|
name = "bozo",
|
|
beta = "10"
|
|
})
|
|
|
|
-- this can of course also work with attributes, but then we don't want to collapse!
|
|
|
|
config = [[
|
|
<config>
|
|
<alpha type='number'>1.3</alpha>
|
|
<beta type='number'>10</beta>
|
|
<name type='string'>bozo</name>
|
|
</config>
|
|
]]
|
|
d,err = xml.parse(config)
|
|
if not d then print(err); os.exit(1) end
|
|
|
|
match([[
|
|
<config>
|
|
{{<_- type='$1'>$2</_->}}
|
|
</config>
|
|
]],{
|
|
alpha = {"number","1.3"},
|
|
beta = {"number","10"},
|
|
name = {"string","bozo"},
|
|
})
|
|
|
|
d,err = xml.parse [[
|
|
|
|
<configuremap>
|
|
<configure name="NAME" value="ImageMagick"/>
|
|
<configure name="LIB_VERSION" value="0x651"/>
|
|
<configure name="LIB_VERSION_NUMBER" value="6,5,1,3"/>
|
|
<configure name="RELEASE_DATE" value="2009-05-01"/>
|
|
<configure name="VERSION" value="6.5.1"/>
|
|
<configure name="CC" value="vs7"/>
|
|
<configure name="HOST" value="windows-unknown-linux-gnu"/>
|
|
<configure name="DELEGATES" value="bzlib freetype jpeg jp2 lcms png tiff x11 xml wmf zlib"/>
|
|
<configure name="COPYRIGHT" value="Copyright (C) 1999-2009 ImageMagick Studio LLC"/>
|
|
<configure name="WEBSITE" value="http://www.imagemagick.org"/>
|
|
|
|
</configuremap>
|
|
]]
|
|
if not d then print(err); os.exit(1) end
|
|
--xml.debug = true
|
|
|
|
res,err = d:match [[
|
|
<configuremap>
|
|
{{<configure name="$_" value="$0"/>}}
|
|
</configuremap>
|
|
]]
|
|
|
|
asserteq(res,{
|
|
HOST = "windows-unknown-linux-gnu",
|
|
COPYRIGHT = "Copyright (C) 1999-2009 ImageMagick Studio LLC",
|
|
NAME = "ImageMagick",
|
|
LIB_VERSION = "0x651",
|
|
VERSION = "6.5.1",
|
|
RELEASE_DATE = "2009-05-01",
|
|
WEBSITE = "http://www.imagemagick.org",
|
|
LIB_VERSION_NUMBER = "6,5,1,3",
|
|
CC = "vs7",
|
|
DELEGATES = "bzlib freetype jpeg jp2 lcms png tiff x11 xml wmf zlib"
|
|
})
|
|
|
|
-- short excerpt from
|
|
-- /usr/share/mobile-broadband-provider-info/serviceproviders.xml
|
|
|
|
d = xml.parse [[
|
|
<serviceproviders format="2.0">
|
|
<country code="za">
|
|
<provider>
|
|
<name>Cell-c</name>
|
|
<gsm>
|
|
<network-id mcc="655" mnc="07"/>
|
|
<apn value="internet">
|
|
<username>Cellcis</username>
|
|
<dns>196.7.0.138</dns>
|
|
<dns>196.7.142.132</dns>
|
|
</apn>
|
|
</gsm>
|
|
</provider>
|
|
<provider>
|
|
<name>MTN</name>
|
|
<gsm>
|
|
<network-id mcc="655" mnc="10"/>
|
|
<apn value="internet">
|
|
<dns>196.11.240.241</dns>
|
|
<dns>209.212.97.1</dns>
|
|
</apn>
|
|
</gsm>
|
|
</provider>
|
|
<provider>
|
|
<name>Vodacom</name>
|
|
<gsm>
|
|
<network-id mcc="655" mnc="01"/>
|
|
<apn value="internet">
|
|
<dns>196.207.40.165</dns>
|
|
<dns>196.43.46.190</dns>
|
|
</apn>
|
|
<apn value="unrestricted">
|
|
<name>Unrestricted</name>
|
|
<dns>196.207.32.69</dns>
|
|
<dns>196.43.45.190</dns>
|
|
</apn>
|
|
</gsm>
|
|
</provider>
|
|
<provider>
|
|
<name>Virgin Mobile</name>
|
|
<gsm>
|
|
<apn value="vdata">
|
|
<dns>196.7.0.138</dns>
|
|
<dns>196.7.142.132</dns>
|
|
</apn>
|
|
</gsm>
|
|
</provider>
|
|
</country>
|
|
|
|
</serviceproviders>
|
|
]]
|
|
|
|
res = d:match [[
|
|
<serviceproviders>
|
|
{{<country code="$_">
|
|
{{<provider>
|
|
<name>$0</name>
|
|
</provider>}}
|
|
</country>}}
|
|
</serviceproviders>
|
|
]]
|
|
|
|
asserteq(res,{
|
|
za = {
|
|
"Cell-c",
|
|
"MTN",
|
|
"Vodacom",
|
|
"Virgin Mobile"
|
|
}
|
|
})
|
|
|
|
res = d:match [[
|
|
<serviceproviders>
|
|
<country code="$country">
|
|
<provider>
|
|
<name>$name</name>
|
|
<gsm>
|
|
<apn value="$apn">
|
|
<dns>196.43.46.190</dns>
|
|
</apn>
|
|
</gsm>
|
|
</provider>
|
|
</country>
|
|
</serviceproviders>
|
|
]]
|
|
|
|
asserteq(res,{
|
|
name = "Vodacom",
|
|
country = "za",
|
|
apn = "internet"
|
|
})
|
|
|
|
-- can always use xmlification to generate your templates...
|
|
|
|
local SP, country, provider, gsm, apn, dns = xml.tags 'serviceprovider, country, provider, gsm, apn, dns'
|
|
|
|
t = SP{country{code="$country",provider{
|
|
name '$name', gsm{apn {value="$apn",dns '196.43.46.190'}}
|
|
}}}
|
|
|
|
print(xml.tostring(t,' ',' '))
|