[原创]从Confluence获取html table并将其序列化为C#类文件的工具
公司项目的游戏数据模型文档写在Confluence上,由于在项目初期模型变动比较频繁,手工去将文档中最新的模型结构同步到代码中比较费时费力,而且还很容易出错,于是写了一个小工具来自动化这个同步更新模型到代码中的工作。
如下是一个野怪的数据模型文档:

最终在Unity的C#代码中它会是这个形式:
using UnityEngine;
using System.Collections; public class MonsterData
{
public int monsterId; //人物id
public string name; //怪物名称
public int hp; //怪物最大生命值
public int dodgeRate; //躲闪几率
public int hitRate; //命中几率
public int critHitRate; //暴击几率
public string description; //描述
public int exp; //经验
public int atk; //攻击
public int def; //防御
public string imageName; //怪物图片的名字
public int coins; //击杀怪物获得的金币数
public int isBoss; //是否是Boss
}
我们需要的就是将图1中得结构自动写成包含以上代码内容的C#文件。
下面说说具体的思路
首先,出于从实现难度和跨平台(前端开发用Mac后端开发用Windows)的考虑,我选择用Python来实现这个工具;
然后,分析这个问题可以知道,这个问题可以分解成2个小的问题来解决:
1.从Conflunce上获取对应文档页面的html table;
2.本地解析这个html table后,将其按照C#类的格式写入到文件中。
对于第一个问题
Confluence自带了Remote API,给开发者提供了非常方便的接口来访问或者更改指定页面的数据,点击这里可以查看它的官方文档。不过这个Remote API默认是关闭的,需要手工在设置里面开启,具体开启的步骤可以看这里,每个版本可能设置的布局略有不同,但是设置的东西都是一样的。
在python中可以使用xmlrpclib来调用Confluence的API。具体的实例可以看这两个链接:Updating a Confluence Wiki with a script和modify wiki page confluence programmatically.这样,第一个问题就解决了。
这里插一句,我在开始的时候不知道有这个Remote API,所以尝试过不用他来实现获取Confluence的页面内容,能够访问到对应的页面,可是一直拿不到想要的html内容,不知道是什么问题,后来因为知道了Remote API,也没再继续尝试自己去获取了,有时间再研究以下。
对于第二个问题
解析html可以用python的库beautifulsoup来实现。关于beautifulsoup你可以看这里。这个beautifulsoup不仅名字好看,功能也异常强大。
好了,解决问题的思路确定了,下面我们可以动手来实现这个工具了。以下便是我实现的代码,python写的不多,所以代码可能比较丑,见谅:)
#!/usr/bin/python from bs4 import BeautifulSoup #for change encoding
import sys #for login in confluence
import xmlrpclib import os def mkdir(path): path = path.strip() path = path.rstrip("\\") isExists = os.path.exists(path) if not isExists:
print path + ' create successfully!'
os.makedirs(path)
return True
else:
print path + ' exists!'
return False def makeTableContentList(table):
result = []
allrows = table.findAll('tr')
rowIndex = 0
for row in allrows:
result.append([])
#exclude the strike one
if row.findAll('s'):
continue allcols = row.findAll('td')
#print "rowIndex = ",rowIndex
#print "allcols = ",allcols for col in allcols:
#print "col",col
thestrings = [unicode(s) for s in col.findAll(text=True)]
thetext = ''.join(thestrings) result[-1].append(thetext)
rowIndex += 1
return result def makeFile(tableContentList): className = tableContentList[0][0] outputFile = file("output/" + className + ".cs","w") #start to write file #write header
outputFile.write("using UnityEngine;\n")
outputFile.write("using System.Collections;\n\n")
outputFile.write("public class " + className + "\n{\n") #write members
rowCounter = 0
for row in tableContentList:
if row and rowCounter > 0: #rowCounter == 0 is className #--------format---------
beginSpaces = " public "
typeString = "{:<12}".format(row[0])
memberName = "{:<30}".format(row[1] + ";")
comments = "" if len(row[2]) > 1:
comments = " //" + row[2] s = beginSpaces + typeString + memberName + comments + "\n" outputFile.write(s) rowCounter += 1 #write tail
outputFile.write("}\n") outputFile.close() def setDefaultEncodingUTF8():
reload(sys)
sys.setdefaultencoding('utf-8') def loadConfluencePage(pageID): # login Confluence
CONFLUENCE_URL = "http://192.168.1.119:8090/rpc/xmlrpc"
CONFLUENCE_USER_NAME = "userName" # use your Confluence user Name
CONFLUENCE_PASSWORD = "password" # use your Confluence password # get this from the page url while editing
# e.g. ../editpage.action?pageId=132350005 <-- here
#PAGE_ID = "4686604" client = xmlrpclib.Server(CONFLUENCE_URL, verbose = 0)
auth_token = client.confluence2.login(CONFLUENCE_USER_NAME, CONFLUENCE_PASSWORD)
page = client.confluence2.getPage(auth_token, pageID) htmlContent = page['content'] client.confluence2.logout(auth_token) return htmlContent def main(): #change Encoding to UTF8
setDefaultEncodingUTF8() #make output directory
mkdir(sys.path[0] + "/output") #there are two pages contain data model
pageIDs = ("","") for pageID in pageIDs: print "Make data in page with id: ",pageID htmlContent = loadConfluencePage(pageID) soup = BeautifulSoup(htmlContent)
#print soup.prettify() tables = soup.findAll('table') for table in tables:
#print table
result = makeTableContentList(table)
makeFile(result)
#print "result = "
#print result print "Make Over! Have a nice day!" if __name__ == "__main__":
main()
OK,就到这里,希望大家喜欢:)
转载请注明出处,谢谢:)
[原创]从Confluence获取html table并将其序列化为C#类文件的工具的更多相关文章
- Confluence 6 安装补丁类文件
Atlassian 支持或者 Atlassian 缺陷修复小组可能针对有一些关键问题会提供补丁来解决这些问题,但是这些问题还没有放到下一个更新版本中.这些问题将会使用 Class 类文件同时在官方 J ...
- mysql——获取所有table名和table字段名。
获取database所有table名: (参考:http://stackoverflow.com/questions/2780284/how-to-get-all-table-names-from-a ...
- js&jquery获取指定table指定行里面的内容
js&jquery获取指定table指定行里面的内容 CreateTime--2018年5月18日11:46:04 Author:Marydon 1.展示 代码展示 <table s ...
- 【原创】java 获取十个工作日之前或之后的日期(算当天)-完美解决-费元星
[原创]java 获取十个工作日之后的日期(算当天)-完美解决-费元星(仅考虑星期六星期天) /** * * 根据开始日期 ,需要的工作日天数 ,计算工作截止日期,并返回截止日期 * @param s ...
- 如果当前地图文档中有独立的Table,通过Engine如何获取该Table?
将IMap转为ITableCollection,通过ITableCollection.get_Table(int index);来获取该Table
- 一个简单的C#获取Session、设置Session类文件
一个简单的C#获取Session.设置Session类文件,本类主要实现大家最常用的两个功能: 1.GetSession(string name)根据session名获取session对象: 2.Se ...
- .NET C#利用反射获取类文件以及其中的方法&属性 并获取类及方法上的特性
了解C#特性类并声明我们自己的特性类[AttributeTest]代码如下 using System; namespace AttributeTest { /* 特性说明 特性本质是一个继承和使用了系 ...
- 获取指定开始行数$start,跨度$limit的文件内容
// 获取指定开始行数$page,跨度$step的文件内容 function getLine($file_name, $start, $limit) { $f = new SplFileObject( ...
- [原创作品] 对获取多层json值的封装
今天篇头不废话了,交流加群:164858883 在我们接收后端返回的json数据的时候,在数据缺失的时候,如果直接接收会导致致命错误的发生.可能有些同学会说通常都会有,不用判断直接获取也行.之前我也是 ...
随机推荐
- JAVA:23种设计模式详解(转)2
我们接着讨论设计模式,上篇文章我讲完了5种创建型模式,这章开始,我将讲下7种结构型模式:适配器模式.装饰模式.代理模式.外观模式.桥接模式.组合模式.享元模式.其中对象的适配器模式是各种模式的起源,我 ...
- python 常用数据结构使用
python 字典操作 http://www.cnblogs.com/kaituorensheng/archive/2013/01/24/2875456.html python 字典排序 http:/ ...
- TCL语言笔记:TCL中的列表操作
一.介绍 列表则是具有特殊解释的字符串.Tcl 中的列表操作和其它 Tcl 命令一样具有相同的结构.列表可应用在诸如 foreach 这样的以列表为变元的循环命令中,也应于构建 eval 命令的延迟命 ...
- SQLite数据库的体系结构(翻译自sqlite.org)
$1 简介 本文档描述了SQLite库的体系结构,这些信息对那些想理解和修改SQLite的内部工作机制的人是有用的. 下图显示了SQLite的主要组成部件及其相互关系,下面的内容将描述每一 ...
- Android:设计之屏幕适配
据统计目前市场Android手机的分辨率有是10余种,分辨率如此广泛使得我们在处理分辨率适应方便遇到不少难题,本文就此难点记录设计与实际布局中的解决技巧. 以320x480为蓝本设计布局 因为Andr ...
- Android如何获取开机启动项列表
static final String BOOT_START_PERMISSION = "android.permission.RECEIVE_BOOT_COMPLETED"; p ...
- 构建linux内核源码树
编写驱动程序时,需要内核源码树的支持.内核源码树时从内核源代码编译得到的.下面开始构造内核源代码的步骤.以Ubuntu为例子 1. 下载内源代码,位置www.kernel.org. (注意:源码树内核 ...
- 8天学通MongoDB——第八天 驱动实践
作为系列的最后一篇,得要说说C#驱动对mongodb的操作,目前驱动有两种:官方驱动和samus驱动,不过我个人还是喜欢后者, 因为提供了丰富的linq操作,相当方便. 官方驱动:https://gi ...
- Mac系统在终端中查看CPU信息的命令
在mac os x的终端中以命令行的形式查看本机cpu信息: sysctl -n machdep.cpu.brand_string E.G. lis-mbp:Home jenkins$ sysctl ...
- fzu Problem 2140 Forever 0.5(推理构造)
题目:http://acm.fzu.edu.cn/problem.php?pid=2140 题意: 题目大意:给出n,要求找出n个点,满足: 1)任意两点间的距离不超过1: 2)每个点与(0,0)点的 ...