[原创]从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数据的时候,在数据缺失的时候,如果直接接收会导致致命错误的发生.可能有些同学会说通常都会有,不用判断直接获取也行.之前我也是 ...
随机推荐
- lintcode 中等题:Palindrome Linked List 回文链表
题目 回文链表 设计一种方式检查一个链表是否为回文链表. 样例 1->2->1 就是一个回文链表. 挑战 O(n)的时间和O(1)的额外空间. 解题 法一: 再定义一个链表,存放链表反转的 ...
- Delphi判断字符串是否是数字、字母、大小写字母
function IsNumberic(Vaule:String):Boolean; //判断Vaule是不是数字 var i:integer; begin result:=true; //设置返回值 ...
- Shuffle和排序
MapReduce确保每个reducer的输入都按键排序.系统执行排序的过程——将map输出作为输入传给reducer——称为shuffle.shuffle属于不断被优化和改进的代码库的一部分,从许多 ...
- UVa 10075 - Airlines
航线算球面距离,需要经纬度转空间坐标. 任意两点间距离用Floyd求出来,查询时直接查表. #include <cstdio> #include <map> #include ...
- android下activity中多个listview只允许主界面滚动
之前发现了自己的APP在处理两个listview时产生的一个bug.当两个listview中的item数量多出手机屏幕时,listview不能显示完全.一开始觉得只要加一个scrollview就可以了 ...
- ios ableviewcell的动态加载数据,模仿喜马拉雅动态数据加载
iphone(UITableViewCell)动态加载图片http://developer.apple.com/library/ios/#samplecode/LazyTableImages/Intr ...
- BZOJ 2844 albus就是要第一个出场(高斯消元)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2844 题意: 给出一个长度为n的正整数数列A.每次选出A的一个子集进行抑或(空集抑或值为 ...
- bundle update: env: ruby_executable_hooks: No such file or directory
please open a bug here: https://github.com/mpapis/executable-hooks/issues as a temporary fix try: rv ...
- iOS开发:Swift多线程GCD的使用
除了上一篇文章说到到NSThread线程,还有一个GCD(Grand Central Dispath),是Apple新开发的一个解决多核编程的解决方案,充分的利用CPU资源,将所有的任务,放到一个任务 ...
- 从客户端中检测到有潜在危险的 Request.Form 值-解决方案
环境:VS2010 1.页头上加上ValidateRequest="false" <%@ Page Language="C#" ValidateReque ...