公司项目的游戏数据模型文档写在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 scriptmodify 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#类文件的工具的更多相关文章

  1. Confluence 6 安装补丁类文件

    Atlassian 支持或者 Atlassian 缺陷修复小组可能针对有一些关键问题会提供补丁来解决这些问题,但是这些问题还没有放到下一个更新版本中.这些问题将会使用 Class 类文件同时在官方 J ...

  2. mysql——获取所有table名和table字段名。

    获取database所有table名: (参考:http://stackoverflow.com/questions/2780284/how-to-get-all-table-names-from-a ...

  3. js&jquery获取指定table指定行里面的内容

      js&jquery获取指定table指定行里面的内容 CreateTime--2018年5月18日11:46:04 Author:Marydon 1.展示 代码展示 <table s ...

  4. 【原创】java 获取十个工作日之前或之后的日期(算当天)-完美解决-费元星

    [原创]java 获取十个工作日之后的日期(算当天)-完美解决-费元星(仅考虑星期六星期天) /** * * 根据开始日期 ,需要的工作日天数 ,计算工作截止日期,并返回截止日期 * @param s ...

  5. 如果当前地图文档中有独立的Table,通过Engine如何获取该Table?

    将IMap转为ITableCollection,通过ITableCollection.get_Table(int index);来获取该Table

  6. 一个简单的C#获取Session、设置Session类文件

    一个简单的C#获取Session.设置Session类文件,本类主要实现大家最常用的两个功能: 1.GetSession(string name)根据session名获取session对象: 2.Se ...

  7. .NET C#利用反射获取类文件以及其中的方法&属性 并获取类及方法上的特性

    了解C#特性类并声明我们自己的特性类[AttributeTest]代码如下 using System; namespace AttributeTest { /* 特性说明 特性本质是一个继承和使用了系 ...

  8. 获取指定开始行数$start,跨度$limit的文件内容

    // 获取指定开始行数$page,跨度$step的文件内容 function getLine($file_name, $start, $limit) { $f = new SplFileObject( ...

  9. [原创作品] 对获取多层json值的封装

    今天篇头不废话了,交流加群:164858883 在我们接收后端返回的json数据的时候,在数据缺失的时候,如果直接接收会导致致命错误的发生.可能有些同学会说通常都会有,不用判断直接获取也行.之前我也是 ...

随机推荐

  1. 【memcache缓存专题(2)】memcache安装与命令行使用

    进新公司一个多月了,一直没有时间来更新,后续还是要保持着每日更新的频率 安装 在windows上安装 略(都玩到缓存的程度了,就没必要在windows上捣弄了) 给个参考: http://blog.c ...

  2. 2014--9=17 软工二班 MyEclipse blue==修改浏览器语言

  3. 微信开发之——Php批量生成带参数的二维码

    带参数的二维码对于渠道营销推广来说是很有用的,可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送,可喜的是微信开通了这个接口,那下面就来研究一下吧. 具体接口说明请参见,微信公众平 ...

  4. Centos硬件信息查看命令

    [root@yan-001 ~] # uname -a # 查看内核/操作系统/CPU信息的linux系统信息命令 [root@yan-001 ~] # head -n 1 /etc/issue # ...

  5. linux命令-shopt

    shopt命令 shopt命令用于显示和设置shell中的行为选项,通过这些选项以增强shell易用性.shopt命令若不带任何参数选项,则可以显示所有可以设置的shell操作选项. 开启与关闭 开启 ...

  6. Android权限安全(5)组件的android:exported属性

    Android四大组件都有 android:exported 属性 android:exported="true" 时 表示该组件是公开的,其它组件可以访问这个组件 android ...

  7. 基于eclipse创建android的helloworld工程

    基于eclipse创建android的helloworld工程 之前用过Android studio感觉很慢,决定采用eclipse来学习Android开发.下面来看是怎么创建的. 选择File--- ...

  8. 安卓学习之--如何关闭所有的activity

    根据Activity的声明周期 方法1   我们知道Android的窗口类提供了历史栈,我们可以通过stack的原理来巧妙的实现,这里我们在A窗口打开B窗口时在Intent中直接加入标志 Intent ...

  9. 通过AJAX与ASP.NET结合实现的仿GridView增删改查功能

    jQurey代码部分: 1.    <script type="text/javascript"> 2.            var flag = 0; 3. 4.  ...

  10. 修改数据库中group_concat的返回结果的长度限制

    修改数据库中group_concat的返回结果的长度限制 我们可以使用Mysql的客户端管理工具,Sqlyog 新建一个查询编辑器 显示  SHOW VARIABLES LIKE "grou ...