XMind思維導圖建立、解析、更新一站式解決方案(開源)

devinzhang發表於2019-01-02

mind_mapping

XMind 是基於 Python 實現,提供了對 XMind思維導圖進行建立、解析、更新的一站式解決方案!

一、安裝方式

pip3 install XMind  

or

pip3 install xmind
複製程式碼

二、版本升級

pip3 install -U XMind
複製程式碼

三、使用方式

1、建立XMind檔案

def gen_my_xmind_file():  
    # 1、如果指定的XMind檔案存在,則載入,否則建立一個新的
    workbook = xmind.load("my.xmind")
    
    # 2、獲取第一個畫布(Sheet),預設新建一個XMind檔案時,自動建立一個空白的畫布
    sheet1 = workbook.getPrimarySheet()
    # 對第一個畫布進行設計完善,具體參照下一個函式
    design_sheet1(sheet1)
    
    # 3、建立第二個畫布
    gen_sheet2(workbook, sheet1)
    
    # 4、儲存(如果指定path引數,另存為該檔名)
    xmind.save(workbook, path='test.xmind')
複製程式碼

first sheet

def design_sheet1(sheet1):
    # ***** 第一個畫布 *****
    sheet1.setTitle("first sheet")  # 設定畫布名稱

    # 獲取畫布的中心主題,預設建立畫布時會新建一個空白中心主題
    root_topic1 = sheet1.getRootTopic()
    root_topic1.setTitle("root node")  # 設定主題名稱

    # 建立一個子主題,並設定其名稱
    sub_topic1 = root_topic1.addSubTopic()
    sub_topic1.setTitle("first sub topic")

    sub_topic2 = root_topic1.addSubTopic()
    sub_topic2.setTitle("second sub topic")

    sub_topic3 = root_topic1.addSubTopic()
    sub_topic3.setTitle("third sub topic")

    sub_topic4 = root_topic1.addSubTopic()
    sub_topic4.setTitle("fourth sub topic")

    # 除了新建子主題,還可以建立自由主題(注意:只有中心主題支援建立自由主題)
    detached_topic1 = root_topic1.addSubTopic(topics_type=TOPIC_DETACHED)
    detached_topic1.setTitle("detached topic")
    detached_topic1.setPosition(0, 30)

    # 建立一個子主題的子主題
    sub_topic1_1 = sub_topic1.addSubTopic()
    sub_topic1_1.setTitle("I'm a sub topic too")
複製程式碼

second sheet

def gen_sheet2(workbook, sheet1):
    # ***** 設計第二個畫布 *****
    sheet2 = workbook.createSheet()
    sheet2.setTitle("second sheet")

    # 獲取畫布的中心主題
    root_topic2 = sheet2.getRootTopic()
    root_topic2.setTitle("root node")

    # 使用另外一種方法建立子主題
    topic1 = TopicElement(ownerWorkbook=workbook)
    # 給子主題新增一個主題間超連結,通過指定目標主題ID即可,這裡連結到第一個畫布
    topic1.setTopicHyperlink(sheet1.getID())
    topic1.setTitle("redirection to the first sheet")

    topic2 = TopicElement(ownerWorkbook=workbook)
    topic2.setTitle("topic with an url hyperlink")
    # 給子主題新增一個URL超連結
    topic2.setURLHyperlink("https://github.com/zhuifengshen/xmind")

    topic3 = TopicElement(ownerWorkbook=workbook)
    topic3.setTitle("third node")
    # 給子主題新增一個備註(快捷鍵F4)
    topic3.setPlainNotes("notes for this topic")
    topic3.setTitle("topic with \n notes")

    topic4 = TopicElement(ownerWorkbook=workbook)
    # 給子主題新增一個檔案超連結
    topic4.setFileHyperlink("logo.png")
    topic4.setTitle("topic with a file")

    topic1_1 = TopicElement(ownerWorkbook=workbook)
    topic1_1.setTitle("sub topic")
    # 給子主題新增一個標籤(目前XMind軟體僅支援新增一個,快捷鍵)
    topic1_1.addLabel("a label")

    topic1_1_1 = TopicElement(ownerWorkbook=workbook)
    topic1_1_1.setTitle("topic can add multiple markers")
    # 給子主題新增兩個圖示
    topic1_1_1.addMarker(MarkerId.starBlue)
    topic1_1_1.addMarker(MarkerId.flagGreen)

    topic2_1 = TopicElement(ownerWorkbook=workbook)
    topic2_1.setTitle("topic can add multiple comments")
    # 給子主題新增一個批註(評論)
    topic2_1.addComment("I'm a comment!")
    topic2_1.addComment(content="Hello comment!", author='devin')

    # 將建立好的子主題新增到其父主題下
    root_topic2.addSubTopic(topic1)
    root_topic2.addSubTopic(topic2)
    root_topic2.addSubTopic(topic3)
    root_topic2.addSubTopic(topic4)
    topic1.addSubTopic(topic1_1)
    topic2.addSubTopic(topic2_1)
    topic1_1.addSubTopic(topic1_1_1)

    # 給中心主題下的每個子主題新增一個優先順序圖示
    topics = root_topic2.getSubTopics()
    for index, topic in enumerate(topics):
        topic.addMarker("priority-" + str(index + 1))

    # 新增一個主題與主題之間的聯絡
    sheet2.createRelationship(topic1.getID(), topic2.getID(), "relationship test") 
複製程式碼

具體程式碼參考:create_xmind.py

2、解析XMind檔案

(1) 將XMind檔案轉換為Dict資料 / JSON資料
import xmind
workbook = xmind.load('demo.xmind')
print(workbook.getData())
print(workbook.to_prettify_json())


Output:

[                                                                # 畫布列表
    {                                                            # 第1個畫布資料
        "id": "2cc3b068922063a81a20029655",                      # 畫布ID
        "title": "first sheet",                                  # 畫布名稱
        "topic": {                                               # 中心主題
            "id": "2cc3b06892206f95288e487b6c",                  # 主題ID
            "link": null,                                        # 超連結資訊
            "title": "root node",                                # 主題名稱
            "note": null,                                        # 備註資訊
            "label": null,                                       # 便籤資訊
            "comment": null,                                     # 批註(評論)資訊
            "markers": [],                                       # 圖示列表
            "topics": [                                          # 子主題列表
                {
                    "id": "2cc3b06892206c816e1cb55ddc",          # 子主題ID
                    "link": null,
                    "title": "first sub topic",
                    "note": null,
                    "label": null,
                    "comment": null,
                    "markers": [],
                    "topics": [                                  # 子主題下的子主題列表
                        {
                            "id": "b0ed74214dbca939935b981906",
                            "link": null,
                            "title": "I'm a sub topic too",
                            "note": null,
                            "label": null,
                            "comment": null,
                            "markers": []
                        }
                    ]
                },
                {
                    "id": "b0ed74214dbca693b947ef03fa",
                    "link": null,
                    "title": "second sub topic",
                    "note": null,
                    "label": null,
                    "comment": null,
                    "markers": []
                },
                {
                    "id": "b0ed74214dbca1fe9ade911b94",
                    "link": null,
                    "title": "third sub topic",
                    "note": null,
                    "label": null,
                    "comment": null,
                    "markers": []
                },
                {
                    "id": "b0ed74214dbcac00c0eb368b53",
                    "link": null,
                    "title": "fourth sub topic",
                    "note": null,
                    "label": null,
                    "comment": null,
                    "markers": []
                }
            ]
        }
    },
    {
        "id": "b0ed74214dbcafdd0799f81ebf",
        "title": "second sheet",                                         # 第2個畫布資料
        "topic": {
            "id": "b0ed74214dbcac7567f88365c2",
            "link": null,
            "title": "root node",
            "note": null,
            "label": null,
            "comment": null,
            "markers": [],
            "topics": [
                {
                    "id": "b0ed74214dbca8bfdc2b60df47",
                    "link": "xmind:#2cc3b068922063a81a20029655",
                    "title": "redirection to the first sheet",
                    "note": null,
                    "label": null,
                    "comment": null,
                    "markers": [
                        "priority-1"
                    ],
                    "topics": [
                        {
                            "id": "e613d79938591579e707a7a161",
                            "link": null,
                            "title": "sub topic",
                            "note": null,
                            "label": "a label",
                            "comment": null,
                            "markers": [],
                            "topics": [
                                {
                                    "id": "e613d799385912cca5eb579fb3",
                                    "link": null,
                                    "title": "topic can add multiple markers",
                                    "note": null,
                                    "label": null,
                                    "comment": null,
                                    "markers": [
                                        "star-blue",
                                        "flag-green"
                                    ]
                                }
                            ]
                        }
                    ]
                },
                {
                    "id": "e613d79938591ef98b64a768db",
                    "link": "https://xmind.net",
                    "title": "topic with an url hyperlink",
                    "note": null,
                    "label": null,
                    "comment": null,
                    "markers": [
                        "priority-2"
                    ],
                    "topics": [
                        {
                            "id": "e613d799385916ed8f3ea382ca",
                            "link": null,
                            "title": "topic can add multiple comments",
                            "note": null,
                            "label": null,
                            "comment": "I'm a comment!\nHello comment!",
                            "markers": []
                        }
                    ]
                },
                {
                    "id": "e613d799385919451116404d66",
                    "link": null,
                    "title": "topic with \n notes",
                    "note": "notes for this topic",
                    "label": null,
                    "comment": null,
                    "markers": [
                        "priority-3"
                    ]
                },
                {
                    "id": "e613d7993859156671fa2c12a5",
                    "link": "file:///Users/zhangchuzhao/Project/python/tmp/xmind/example/xminddemo/logo.png",
                    "title": "topic with a file",
                    "note": null,
                    "label": null,
                    "comment": null,
                    "markers": [
                        "priority-4"
                    ]
                }
            ]
        }
    }
]
複製程式碼
(2)將畫布轉換為Dict資料
import xmind
workbook = xmind.load('demo.xmind')
sheet = workbook.getPrimarySheet()
print(sheet.getData())


Output:

{
    "id": "2cc3b068922063a81a20029655",
    "title": "first sheet",
    "topic": {
        "id": "2cc3b06892206f95288e487b6c",
        "link": null,
        "title": "root node",
        "note": null,
        "label": null,
        "comment": null,
        "markers": [],
        "topics": [
            {
                "id": "2cc3b06892206c816e1cb55ddc",
                "link": null,
                "title": "first sub topic",
                "note": null,
                "label": null,
                "comment": null,
                "markers": [],
                "topics": [
                    {
                        "id": "b0ed74214dbca939935b981906",
                        "link": null,
                        "title": "I'm a sub topic too",
                        "note": null,
                        "label": null,
                        "comment": null,
                        "markers": []
                    }
                ]
            },
            {
                "id": "b0ed74214dbca693b947ef03fa",
                "link": null,
                "title": "second sub topic",
                "note": null,
                "label": null,
                "comment": null,
                "markers": []
            },
            {
                "id": "b0ed74214dbca1fe9ade911b94",
                "link": null,
                "title": "third sub topic",
                "note": null,
                "label": null,
                "comment": null,
                "markers": []
            },
            {
                "id": "b0ed74214dbcac00c0eb368b53",
                "link": null,
                "title": "fourth sub topic",
                "note": null,
                "label": null,
                "comment": null,
                "markers": []
            }
        ]
    }
}
複製程式碼
(3) 將主題轉換為Dict資料
import xmind
workbook = xmind.load('demo.xmind')
sheet = workbook.getPrimarySheet()
root_topic = sheet.getRootTopic()
print(root_topic.getData())


Output:

{
    "id": "2cc3b06892206f95288e487b6c",
    "link": null,
    "title": "root node",
    "note": null,
    "label": null,
    "comment": null,
    "markers": [],
    "topics": [
        {
            "id": "2cc3b06892206c816e1cb55ddc",
            "link": null,
            "title": "first sub topic",
            "note": null,
            "label": null,
            "comment": null,
            "markers": [],
            "topics": [
                {
                    "id": "b0ed74214dbca939935b981906",
                    "link": null,
                    "title": "I'm a sub topic too",
                    "note": null,
                    "label": null,
                    "comment": null,
                    "markers": []
                }
            ]
        },
        {
            "id": "b0ed74214dbca693b947ef03fa",
            "link": null,
            "title": "second sub topic",
            "note": null,
            "label": null,
            "comment": null,
            "markers": []
        },
        {
            "id": "b0ed74214dbca1fe9ade911b94",
            "link": null,
            "title": "third sub topic",
            "note": null,
            "label": null,
            "comment": null,
            "markers": []
        },
        {
            "id": "b0ed74214dbcac00c0eb368b53",
            "link": null,
            "title": "fourth sub topic",
            "note": null,
            "label": null,
            "comment": null,
            "markers": []
        }
    ]
}
複製程式碼
(4) 自定義解析
import xmind
workbook = xmind.load('demo.xmind')
custom_parse_xmind(workbook)


def custom_parse_xmind(workbook):
    elements = {}

    def _echo(tag, element, indent=0):
        title = element.getTitle()
        elements[element.getID()] = title
        print('\t' * indent, tag, ':', pipes.quote(title))

    def dump_sheet(sheet):
        root_topic = sheet.getRootTopic()
        _echo('RootTopic', root_topic, 1)

        for topic in root_topic.getSubTopics() or []:
            _echo('AttachedSubTopic', topic, 2)

        for topic in root_topic.getSubTopics(xmind.core.const.TOPIC_DETACHED) or []:
            _echo('DetachedSubtopic', topic, 2)

        for rel in sheet.getRelationships():
            id1, id2 = rel.getEnd1ID(), rel.getEnd2ID()
            print('Relationship: [%s] --> [%s]' % (elements.get(id1), elements.get(id2)))

    for sheet in workbook.getSheets():
        _echo('Sheet', sheet)
        dump_sheet(sheet)


Output:

 Sheet : 'first sheet'
	 RootTopic : 'root node'
		 AttachedSubTopic : 'first sub topic'
		 AttachedSubTopic : 'second sub topic'
		 AttachedSubTopic : 'third sub topic'
		 AttachedSubTopic : 'fourth sub topic'
		 DetachedSubtopic : 'detached topic'
 Sheet : 'second sheet'
	 RootTopic : 'root node'
		 AttachedSubTopic : 'redirection to the first sheet'
		 AttachedSubTopic : 'topic with an url hyperlink'
		 AttachedSubTopic : 'topic with 
 notes'
		 AttachedSubTopic : 'topic with a file'
Relationship: [redirection to the first sheet] --> [topic with an url hyperlink]
複製程式碼

具體程式碼參考:parse_xmind.py

3、更新儲存XMind檔案

(1)五種儲存方法
import xmind
# 載入XMind檔案demo.xmind
workbook = xmind.load('demo.xmind')  
primary_sheet = workbook.getPrimarySheet()
root_topic = primary_sheet.getRootTopic()
# 給中心主題新增一個星星圖示
root_topic.addMarker(MarkerId.starRed)

# 第1種:預設儲存所有的內容,這裡儲存時另存為xmind_update_demo.xmind(推薦)
xmind.save(workbook=workbook, path='xmind_update_demo.xmind')

# 第2種:只儲存思維導圖內容content.xml核心檔案,適用於沒有新增評論、自定義樣式和附件的情況
xmind.save(workbook=workbook, path='xmind_update_demo1.xmind', only_content=True)

# 第3種:只儲存content.xml、comments.xml、styles.xml三個核心檔案,適用於沒有附件的情況
xmind.save(workbook=workbook, path='xmind_update_demo2.xmind', except_attachments=True)

# 4、除了修改記錄,其他內容都儲存,因為XMind檔案的修改記錄資料夾比較大,以便節約記憶體(推薦)
xmind.save(workbook=workbook, path='xmind_update_demo3.xmind', except_revisions=True)

# 5、不指定儲存路徑,直接更新原檔案
xmind.save(workbook)
複製程式碼

具體程式碼參考:update_xmind.py

(2)XMind檔案結構

xmind file structure

四、工具支援功能

1、支援XMind以下原生元素的建立、解析和更新

  • 畫布(Sheet)
  • 主題(Topic:固定主題、自由主題)
  • 圖示(Marker:圖示名稱)
  • 備註(Note)
  • 標籤(Label)
  • 批註(Comment)
  • 聯絡(Relationship)
  • 樣式(Styles)

2、XMind原生元素

xmind_native_elements

其中,暫不支援的元素(日常也比較少用到)

  • 標註(cllout topic)
  • 概要(summary topic)
  • 外框(outline border)
  • 附件

五、應用場景

XMind2TestCase:一個高效測試用例設計的解決方案!

該方案通過制定測試用例通用模板, 然後使用 XMind 這款廣為流傳且開源的思維導圖工具進行用例設計。

然後基於通用的測試用例模板,在 XMind 檔案上解析並提取出測試用例所需的基本資訊, 合成常見測試用例管理系統所需的用例匯入檔案。

實現將 XMind 設計測試用例的便利與常見測試用例系統的高效管理完美結合起來了,提升日常測試工作的效率!

使用流程如下:

1、使用Web工具進行XMind用例檔案解析

webtool

2、轉換後的用例預覽

testcase preview

3、用例匯入TestLink系統

testlink

4、用例匯入Zentao(禪道)系統

zentao

六、自動化測試與釋出

1、自動化單元測試(TODO: 待上傳)

python3 -m unittest discover
複製程式碼

2、一鍵打 Tag 並上傳至 PYPI

每次在 __ about __.py 更新版本號後,執行以下命令,實現自動化更新打包上傳至 PYPI ,同時根據其版本號自動打 Tag 並推送到倉庫:

python3 setup.py pypi
複製程式碼

upload pypi

七、致謝

在此,衷心感謝 XMind 思維導圖官方創造了這麼一款激發靈感、創意,提升工作、生活效率的高價值生產力產品, 同時還開源 xmind-sdk-python 工具幫助開發者構建自己的 XMind 檔案 ,本專案正是基於此工具進行擴充套件和升級,受益匪淺,感恩!

得益於開源,也將堅持開源,併為開源貢獻自己的點滴之力。後續,將繼續根據實際專案需要,定期進行維護更新和完善,歡迎大夥的使用和意見反饋,謝謝!

(如果本專案對你有幫助的話,也歡迎 star

QA之禪

相關文章