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,' ',' '))