公司项目的游戏数据模型文档写在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. Minimum_Window_Substring两种方法求解

    题目描述: Given a string S and a string T, find the minimum window in S which will contain all the chara ...

  2. 【Linux高频命令专题(20)】du

    概述 显示每个文件和目录的磁盘使用空间. 命令格式 du [选项][文件] 文件缺省就代表当前目录大小 参数 -a或-all 显示目录中个别文件的大小. -b或-bytes 显示目录或文件大小时,以b ...

  3. C语言指针的概念

    在计算机中,所有的数据都是存放在存储器中的.一般把存储器中的一个字节称为一个内存单元,不同的数据类型所占用的内存单元数不等,如整型量占2个单元,字符量占1个单元等,在前面已有详细的介绍.为了正确地访问 ...

  4. C++Builder和VC的比较

    C++Builder和VC的比较 其实很久以前我就想写这篇文章,其原因一方面是因为笔者深深感觉到C++ Builder的确是一个先进与强大的程式开发工具,但更最重要的一点是,我深信C++ Builde ...

  5. [cocoapods]cocoapods问题解决

    错误1. While executing gem no such name 错误原因:gem 网址被挡住了. 解决办法:设置https://ruby.taobao.org/ 详情参考 http://w ...

  6. No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK? 问题

    maven编译项目时出错,提示信息如下: [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3 ...

  7. android从应用到驱动之—camera(1)---程序调用流程

    一.开篇 写博客还得写开篇介绍,可惜,这个不是我所擅长的.就按我自己的想法写吧. 话说camera模块,从上层到底层一共包含着这么几个部分: 1.apk------java语言 2.camera的ja ...

  8. openfire 介绍安装使用

    Openfire 采用Java开发,开源的实时协作(RTC)服务器基于XMPP(Jabber)协议.Openfire安装和使用都非常简单,并利用Web进行管理.单台服务器可支持上万并发用户.您可以使用 ...

  9. java web 下实现文件下载

    来自:http://blog.csdn.net/longshengguoji/article/details/39433307 需求:实现一个具有文件下载功能的网页,主要下载压缩包和图片 两种实现方法 ...

  10. ubuntu13.04下载android4.0.1源码过程

    最初我参考的是老罗的博客http://blog.csdn.net/luoshengyang/article/details/6559955 进行下载安装的,但弄着弄着就发现不太对劲了.这里记录下详细过 ...