I wrote a Python script to read it and output html. Let me try to post it here...
Sorry for the long messy post. The spoiler tags and the source code blocks don't seem to work for me.
import xml.etree.ElementTree as ET
import re
def parse_node(node):
'''
ElementTree indexes by position. Convert to indexing by name of attribute.
'''
imp = {}
for child in node:
tag = child.tag.strip()
text = child.text.strip()
if len(text) > 0:
imp[tag] = text
else:
# get the list associated with this tag
if tag in imp:
attr_list = imp[tag]
else:
attr_list = []
imp[tag] = attr_list
if len(child) > 0:
attr_list.append(parse_node(child)) # recursive call
return imp
def print_improvements(imps, out):
imps_dict = {}
for imp in imps:
imp_type = imp.get('ImprovementType')
if imp_type in imps_dict:
imps_dict[imp_type].append(imp)
else:
imps_dict[imp_type] = [imp]
for k, v in imps_dict.iteritems():
if len(v) == 0: continue
out.write('<h4>%s</h4>\n' % pretty_name(k))
out.write('<table border="1">\n')
out.write(header_row() + '\n')
for imp in v:
out.write(print_improvement(imp))
out.write('</table>\n')
def get_all(node, label, sublabel):
if node.get(label) is None:
return
for el in node[label]: # list
if el.get(sublabel):
yield el[sublabel]
'''
Columns:
Name & UpgradesFrom & Prereqs & Cost & Maintenance & Effects & LevelEffects & NeigbhbourBonus & Other
'''
def header_row():
return '<tr><th>Name</th><th>Upgrades From</th><th>Prereqs</th><th>Cost</th><th>Maintenance</th><th>Effects</th><th>Level Effects</th><th>Adjacency Bonuses</th><th>Other</th></tr>'
def print_improvement(imp):
ret = '<tr>'
ret += '<td>%s</td>' % internal_name(imp)
ret += '<td>%s</td>' % upgrades_from(imp)
ret += '<td>%s</td>' % prereqs(imp)
ret += '<td>%s</td>' % cost(imp)
ret += '<td>%s</td>' % maintenance(imp)
ret += '<td>%s</td>' % effects(imp)
ret += '<td>%s</td>' % level_effects(imp)
ret += '<td>%s</td>' % neighbour_bonus(imp)
ret += '<td>%s</td>' % other_notes(imp)
ret += '</tr>'
return ret
replacement = {'MaxManufacturing': 'Production', 'Manufacturing': 'Social Production',
'GoodsAndServices': 'Morale', 'FoodIncome': 'Food', 'InfluencePerTurn':'Influence',
'ColonyGrossIncome': 'Income', 'CulturePerTurnMerciless': 'Malevolent',
'CulturePerTurnNeutral': 'Pragmatic', 'CulturePerTurnBenevolent': 'Benevolent',
'TradeRouteValueRaw': 'Trade Route Value'}
def pretty_name(name):
if name in replacement:
return replacement[name]
if name.endswith('Tech') or name.endswith('Cost'):
name = name[:-4]
if name.endswith('Ability'):
name = name[:-7]
name = re.sub("([A-Z])"," \g<0>", name)
name = name.replace('ofthe ', ' of the ').replace('of ', ' of ')
return name
def internal_name(imp):
return pretty_name(imp['InternalName'])
def upgrades_from(imp):
for el in get_all(imp, 'Prerequ', 'UpgradesFrom'):
return pretty_name(el)
return ''
def prereqs(imp):
ret = []
for el in get_all(imp, 'Prerequ', 'Techs'):
ret.append(pretty_name(el[0]['Option']))
for el in get_all(imp, 'Prerequ', 'RaceTrait'):
for subel in el:
ret.append('Race Trait: ' + pretty_name(subel['Option']))
for el in get_all(imp, 'Prerequ', 'Culture'):
for subel in el:
ret.append('Ideology: ' + pretty_name(subel['Option']))
for el in get_all(imp, 'Prerequ', 'ColonySponsoringShipyard'):
if el == 'true':
ret.append('Sponsoring shipyard')
for el in get_all(imp, 'Preclusions', 'RaceTrait'):
for subel in el:
ret.append('Race Trait: NOT ' + pretty_name(subel['Option']))
for el in get_all(imp, 'Preclusions', 'Improvement'):
ret.append('NOT ' + pretty_name(el))
return '<br/>'.join(ret)
def cost(imp):
ret = ''
for el in imp.get('Stats'):
if el.get('EffectType') == 'ManufacturingCost':
ret = el.get('Value')
# get all the resource costs
if imp.get('Stats') is None: return ''
for el in imp.get('Stats'):
if (el.get('EffectType') not in ['ManufacturingCost'] and el.get('EffectType').endswith('Cost')) \
or el.get('EffectType') == 'Credits':
if len(ret) > 0:
ret += '<br/>'
ret += stat_str(el)
return ret
def maintenance(imp):
for el in imp.get('Stats'):
if el.get('EffectType') == 'Maintenance':
return el.get('Value')
return ''
def effects(imp):
ret = ''
if imp.get('Stats') is not None:
for el in imp.get('Stats'):
if el.get('EffectType') not in ['Maintenance', 'ManufacturingCost'] and not el.get('EffectType').endswith('Cost') \
and not el.get('EffectType') == 'Credits':
if len(ret) > 0:
ret += '<br/>'
ret += stat_str(el)
if imp.get('Triggers') is not None:
for el in imp.get('Triggers'):
if len(ret) > 0:
ret += '<br/>'
ret += trigger_str(el)
if imp.get('LandPercentageMin') is not None:
if len(ret) > 0:
ret += '<br/>'
ret += 'Terraform: %d%% Land Minimum' % (float(imp.get('LandPercentageMin')) * 100)
return ret
def level_effects(imp):
ret = ''
if imp.get('LevelEffectStats') is not None:
for el in imp.get('LevelEffectStats'):
if el.get('EffectType') not in ['Maintenance', 'ManufacturingCost']:
if len(ret) > 0:
ret += '<br/>'
ret += stat_str(el)
if imp.get('LevelEffectTriggers') is not None:
for el in imp.get('LevelEffectTriggers'):
if len(ret) > 0:
ret += '<br/>'
ret += trigger_str(el)
return ret
def neighbour_bonus(imp):
ret = ''
if imp.get('NeighborBonuses') is None: return ''
for el in imp.get('NeighborBonuses'):
bonus_type = pretty_name(el.get('GiveBonusToNeighborType'))
bonus_value = el.get('NeighborBonusValue')
if len(ret) > 0:
ret += '<br/>'
ret += '%s %s' % (bonus_value, bonus_type)
return ret
def other_notes(imp):
ret = ''
# colony unique
if imp.get('IsColonyUnique') == 'true':
ret += 'Colony Unique <br/>'
if imp.get('IsIndestructible') == 'true':
ret += 'Indestructible <br/>'
# indestructible
return ret
def stat_str(el):
resource = pretty_name(el.get('EffectType'))
value = el.get('Value')
modifier = ''
if el.get('Scope') == 'Global':
modifier = 'Global '
if el['BonusType'] == 'Flat' or el['BonusType'] == 'OneTime':
return '%s %s%s' % (value, modifier, resource)
if el['BonusType'] == 'Multiplier':
return '%.1f%% %s%s' % ((float(value)*100), modifier, resource)
return ''
def trigger_str(el):
ret = ''
for subel in get_all(el, 'PerformAction', 'Action'):
if subel == 'GrantUnitType':
return 'Grants ' + el.get('PerformAction')[0].get('StringParam')
elif subel == 'AwardResearchAmount':
return el.get('PerformAction')[0].get('ValueParam') + ' Research Points'
else:
return el.get('PerformAction')[0].get('Action')
for subel in el.get('Modifier'):
return stat_str(subel)
return ret
################################################################################
def write_improvements_html(f, out_f):
# read improvements
imps = []
tree = ET.parse(f)
for node in tree.getroot():
imp = parse_node(node)
#print imp
#exit()
imps.append(imp)
print len(imps), 'improvements'
out = open(out_f, 'w')
# separate wonders from non-wonders
wonders = [imp for imp in imps if imp.get('IsGalacticWonder') == 'true']
player_wonders = [imp for imp in imps if imp.get('IsPlayerWonder') == 'true']
non_wonders = [imp for imp in imps if imp not in wonders and imp not in player_wonders]
out.write('<html><body>\n')
out.write('<h2>Galactic Wonders</h2>')
print_improvements(wonders, out)
out.write('<h2>Player Wonders</h2>')
print_improvements(player_wonders, out)
out.write('<h2>Improvements</h2>')
print_improvements(non_wonders, out)
out.write('</body></html>')
out.close()
def write_starbase_html(f, out_f):
# read modules
imps = []
tree = ET.parse(f)
for node in tree.getroot():
imp = parse_node(node)
imps.append(imp)
print len(imps), 'modules'
out = open(out_f, 'w')
# separate wonders from non-wonders
out.write('<html><body>\n')
out.write('<h2>Starbase Modules</h2>')
print_starbase(imps, out)
out.write('</body></html>')
out.close()
def print_starbase(imps, out):
imps_dict = {}
for imp in imps:
imp_type = imp.get('SpecializationType')
if imp_type in imps_dict:
imps_dict[imp_type].append(imp)
else:
imps_dict[imp_type] = [imp]
for k, v in imps_dict.iteritems():
if len(v) == 0: continue
out.write('<h4>%s</h4>\n' % pretty_name(k))
out.write('<table border="1">\n')
out.write(header_row_module() + '\n')
for imp in v:
out.write(print_module(imp))
out.write('</table>\n')
def header_row_module():
return '<tr><th>Name</th><th>Upgrades From</th><th>Prereqs</th><th>Cost</th><th>Maintenance</th><th>Effects</th></tr>'
def print_module(imp):
ret = '<tr>'
ret += '<td>%s</td>' % internal_name(imp)
ret += '<td>%s</td>' % upgrades_from(imp)
ret += '<td>%s</td>' % prereqs(imp)
ret += '<td>%s</td>' % cost(imp)
ret += '<td>%s</td>' % maintenance(imp)
ret += '<td>%s</td>' % effects(imp)
ret += '</tr>'
return ret
def write_ship_html(f, out_f):
# read modules
imps = []
tree = ET.parse(f)
for node in tree.getroot():
imp = parse_node(node)
imps.append(imp)
print len(imps), 'components'
out = open(out_f, 'w')
# separate wonders from non-wonders
out.write('<html><body>\n')
out.write('<h2>Ship Components</h2>')
print_ship(imps, out)
out.write('</body></html>')
out.close()
#ShipComponent
def print_ship(imps, out):
imps_dict = {}
for imp in imps:
imp_type = imp.get('Type')
if imp_type in imps_dict:
imps_dict[imp_type].append(imp)
else:
imps_dict[imp_type] = [imp]
for k, v in imps_dict.iteritems():
if len(v) == 0: continue
out.write('<h4>%s</h4>\n' % pretty_name(k))
out.write('<table border="1">\n')
out.write(header_row_module() + '\n')
for imp in v:
out.write(print_module(imp))
out.write('</table>\n')
if __name__ == '__main__':
f = 'ImprovementDefs.xml'
out_f = 'improvements.html'
write_improvements_html(f, out_f)
f = 'StarbaseModuleDefs.xml'
out_f = 'starbase.html'
write_starbase_html(f, out_f)
f = 'ShipComponentDefs.xml'
out_f = 'ship_components.html'
write_ship_html(f, out_f)