VisioのXML構成を調べてみた

はじめに
============================================================

それvisioで欲しいんだよね。
------------------------------------------------------------
最近、blockdiag+SphinxのコラボでDFDやシーケンス図の自動生成に精をだしていた矢先、

* 「visio出力してほしい」
* 「編集したい」

という声が上がってしまいました。
そんなこんなで、visioを自動出力しようかと考えたのですが、

* visioマクロでの生成はイケてない。そもそもVisioがないと動かないし。
* POIのVisio生成は、仕様が難しいうえに、一部対応しきれていないという情報もあり
* IronPythonで実装するのも、C#で実装するのもVisioと変わらないし。
* 自由度の高いフリーソフトも見つからず…。

などの理由で悩んでいました。

visioファイルはXML形式
------------------------------------------------------------
そんななか、実はvisioでよく利用されるファイル形式vdxがただのXML形式のファイルであることを知り、その構成について手探りで調べたメモになります。

簡単な構成でXMLを作成してみる
------------------------------------------------------------

```xml:sample1.vdx
<VisioDocument>
  <StyleSheets/>
  <Masters>
  </Masters>

  <Pages>
    <Page ID="0">
      <PageSheet>
        <PageProps>
          <!-- ページのレイアウト -->
          <PageWidth>10</PageWidth>
          <PageHeight>10</PageHeight>
        </PageProps>
      </PageSheet>
      <Shapes>
        <Shape ID="1" >
          <XForm>
            <!-- 位置 -->
            <PinX>1</PinX>
            <PinY>1</PinY>
            <!-- オブジェクトの大きさ -->
            <Width>2.5</Width>
            <Height>1</Height>
          </XForm>
          <Fill>
            <!-- 背景色 -->
            <FillForegnd F="RGB(255,255,255)"/>
          </Fill>
          <!-- 罫線の詳細定義 -->
          <Line>
            <!-- 太さ -->
            <LineWeight>0.0138889</LineWeight>
            <!-- 色 -->
            <LineColor F="RGB(32,32,140)"/>
            <!-- 普通の線 -->
            <LinePattern>1</LinePattern>
          </Line>
          <!-- 文字定義 -->
          <Char IX="0">
            <Font F="FONTTOID(&quot;Arial&quot;)">0</Font>
            <Color F="RGB(140,32,32)"/>
            <Style>0</Style>
            <Size>0.138889</Size>
          </Char>
          <!-- オブジェクトの線 -->
          <Geom IX="0">
            <!-- 線をつくる点の開始位置 -->
            <MoveTo IX="1">
              <X F="Width*0" />
              <Y F="Height*1" />
            </MoveTo>
            <!-- 線をつくる点(IX="1"と線としてつながる) -->
            <LineTo IX="2">
              <X F="Width*0" />
              <Y F="Height*0" />
            </LineTo>
            <!-- 線をつくる点(IX="2"と線としてつながる) -->
            <LineTo IX="3">
              <X F="Width*1" />
              <Y F="Height*0" />
            </LineTo>
            <!-- 線をつくる点(IX="3"と線としてつながる) -->
            <LineTo IX="4">
              <X F="Width*1" />
              <Y F="Height*1" />
            </LineTo>
            <!-- 線をつくる点(IX="4"と線としてつながる) -->
            <LineTo IX="5">
              <X F="Width*0" />
              <Y F="Height*1" />
            </LineTo>
          </Geom>
          <Text>Sample</Text>
          <!-- 線などを結ぶためのコネクタ -->
          <Connection IX="0">
            <X F="Width*1"/>
            <Y F="Height*0.5"/>
          </Connection>
        </Shape>
      </Shapes>
    </Page>
  </Pages>
</VisioDocument>
```
![sample1.png](https://qiita-image-store.s3.amazonaws.com/0/82321/c2927fb1-14d5-f55a-00a0-bbb92c3f49ce.png)

Masterタグを利用してみる
------------------------------------------------------------------------
上記のような記載をおこなうと、オブジェクトを１つ作る毎に冗長なコードが必要になります。
したがって、visioファイルの容量も大きくなります。

そこでよく利用するオブジェクトをカプセル化するイメージで定義し、インスタンスを生成するように実行することができます。
それがMasterタグになります。

```xml:sample2.vdx
<VisioDocument>
  <StyleSheets/>
  <Masters>
    <Master ID='0' NameU='Normal Object' Name='ただの四角' Prompt='' >
    <!-- Normalな四角 -->
      <Shapes>
        <Shape ID='5' Type='Shape'>
          <!-- オブジェクトの大きさ -->
          <XForm><Width>2</Width><Height>0.75</Height></XForm>
          <!-- 背景色 -->
          <Fill><FillForegnd F="RGB(255,255,255)"/></Fill>
          <Line><LineWeight>0.0138889</LineWeight><LineColor F="RGB(32,32,140)"/><LinePattern>1</LinePattern></Line>
          <Char IX="0"><Font F="FONTTOID(&quot;Arial&quot;)">0</Font><Color F="RGB(0,0,0)"/><Style>0</Style><Size>0.138889</Size></Char>
          <!-- オブジェクトの線 -->
          <Geom IX="0"><MoveTo IX="1"><X F="Width*0" /><Y F="Height*1" /></MoveTo><LineTo IX="2"><X F="Width*0" /><Y F="Height*0" /></LineTo><LineTo IX="3"><X F="Width*1" /><Y F="Height*0" /></LineTo><LineTo IX="4"><X F="Width*1" /><Y F="Height*1" /></LineTo><LineTo IX="5"><X F="Width*0" /><Y F="Height*1" /></LineTo></Geom>
          <!-- 接続点の定義 -->
          <Connection IX='0'><X F='Width*1'/><Y F='Height*0.5'/></Connection>
          <Connection IX='1'><X F='Width*0.5'/><Y Unit='MM'/></Connection>
          <Connection IX='2'><X F='Width*0'/><Y F='Height*0.5'/></Connection>
          <Connection IX='3'><X F='Width*0.5'/><Y Unit='MM' F='Height*1'/></Connection>
        </Shape>
      </Shapes>
    </Master>
  </Masters>

  <Pages>
    <Page ID="0">
      <PageSheet>
        <PageProps>
          <!-- ページのレイアウト -->
          <PageWidth>10</PageWidth>
          <PageHeight>10</PageHeight>
        </PageProps>
      </PageSheet>
      <Shapes>
        <Shape ID="1" Master='0'>
          <XForm><PinX F='2+3*0'/><PinY F='1*1'/></XForm>
          <Text>BL1</Text>
        </Shape>
        <Shape ID="2" Master='0'>
          <XForm><PinX F='2+3*1'/><PinY F='1*2'/></XForm>
          <Text>BL2</Text>
        </Shape>
      </Shapes>
    </Page>
  </Pages>
</VisioDocument>

```
![sample1_2.png](https://qiita-image-store.s3.amazonaws.com/0/82321/9a871f91-7ecc-b175-91f8-4f249c97755d.png)


Masterタグはオーバーライド可能
------------------------------------------------------------------------
また上記例では、行いませんでしたがMasterタグはShapeタグで同じものを定義すればオーバーライドできます。

必要なオブジェクトはMaster化して増やしてく
------------------------------------------------------------------------
あとは、必要なオブジェクトをMaster化して増やせば、Masterは多少冗長になりますが、簡単なVisioの図は自動生成できるようになっていきます。
オブジェクト定義一つ一つは、元々Visioに搭載されているサンプルから取得して、あとは必要な箇所を切り取って利用します。
以下は、その一例になります。

```xml:sample3.vdx
<?xml version='1.0' encoding='utf-8' ?>
<VisioDocument xml:space='preserve' xmlns:vx='http://schemas.microsoft.com/visio/2006/extension' xmlns='http://schemas.microsoft.com/visio/2003/core'>
	<!-- オブジェクト定義 -->
	<Masters>
		<Master ID='0' NameU='Normal Object' Name='ただの四角' Prompt='' >
		<!-- Normalな四角 -->
			<Shapes>
				<Shape ID='5' Type='Shape'>
					<!-- オブジェクトの大きさ -->
					<XForm><Width>2</Width><Height>0.75</Height></XForm>
					<Fill><FillForegnd F="RGB(255,255,255)"/></Fill>
					<Line><LineWeight>0.0138889</LineWeight><LineColor F="RGB(32,32,140)"/><LinePattern>1</LinePattern></Line>
					<Char IX="0"><Font F="FONTTOID(&quot;Arial&quot;)">0</Font><Color F="RGB(0,0,0)"/><Style>0</Style><Size>0.138889</Size></Char>
					<!-- 罫線 -->
					<Geom IX="0"><MoveTo IX="1"><X F="Width*0" /><Y F="Height*1" /></MoveTo><LineTo IX="2"><X F="Width*0" /><Y F="Height*0" /></LineTo><LineTo IX="3"><X F="Width*1" /><Y F="Height*0" /></LineTo><LineTo IX="4"><X F="Width*1" /><Y F="Height*1" /></LineTo><LineTo IX="5"><X F="Width*0" /><Y F="Height*1" /></LineTo></Geom>
					<Connection IX='0'><X F='Width*1'/><Y F='Height*0.5'/></Connection>
					<Connection IX='1'><X F='Width*0.5'/><Y Unit='MM'/></Connection>
					<Connection IX='2'><X F='Width*0'/><Y F='Height*0.5'/></Connection>
					<Connection IX='3'><X F='Width*0.5'/><Y Unit='MM' F='Height*1'/></Connection>
				</Shape>
			</Shapes>
		</Master>
		<!-- ドラム缶 -->
		<Master ID='1' NameU='Data store' Name='データ保管'>
			<Shapes>
				<Shape ID='5' Type='Shape'>
					<!-- オブジェクトの大きさ -->
					<XForm><Width>2</Width><Height>0.75</Height></XForm>
					<TextXForm><TxtPinX Unit='PT' F='Controls.Row_2'>0.3937007874015748</TxtPinX><TxtPinY F='Controls.Row_2.Y'>-0.09444444444444444</TxtPinY><TxtWidth Unit='PT' F='MAX(TEXTWIDTH(TheText),8*Char.Size)'>0.8888888888888888</TxtWidth><TxtHeight F='TEXTHEIGHT(TheText,TxtWidth)'>0.1888888888888889</TxtHeight><TxtLocPinX Unit='PT' F='TxtWidth*0.5'>0.4444444444444444</TxtLocPinX><TxtLocPinY F='TxtHeight*0.5'>0.09444444444444444</TxtLocPinY><TxtAngle>0</TxtAngle></TextXForm>
					<TextBlock><LeftMargin Unit='PT' F='Inh'>0.02777777777777778</LeftMargin><RightMargin Unit='PT' F='Inh'>0.02777777777777778</RightMargin><TopMargin Unit='PT' F='Inh'>0.02777777777777778</TopMargin><BottomMargin Unit='PT' F='Inh'>0.02777777777777778</BottomMargin><VerticalAlign F='Inh'>1</VerticalAlign><TextBkgnd F='Inh'>0</TextBkgnd><DefaultTabStop F='Inh'>0.5</DefaultTabStop><TextDirection F='Inh'>0</TextDirection><TextBkgndTrans F='Inh'>0</TextBkgndTrans></TextBlock>
					<Event><TheData F='No Formula'>0</TheData><TheText F='No Formula'>0</TheText><EventDblClick F='OPENTEXTWIN()'>0</EventDblClick><EventXFMod F='No Formula'>0</EventXFMod><EventDrop F='No Formula'>0</EventDrop></Event>
					<vx:Event xmlns:vx='http://schemas.microsoft.com/visio/2006/extension'><vx:EventMultiDrop F='No Formula'>0</vx:EventMultiDrop></vx:Event>
					<Help><HelpTopic>Vis_D21.chm!#48063</HelpTopic><Copyright V='null'/></Help>
					<Misc><NoObjHandles F='Inh'>0</NoObjHandles><NonPrinting F='Inh'>0</NonPrinting><NoCtlHandles F='Inh'>0</NoCtlHandles><NoAlignBox F='Inh'>0</NoAlignBox><UpdateAlignBox F='Inh'>0</UpdateAlignBox><HideText F='Inh'>0</HideText><DynFeedback F='Inh'>0</DynFeedback><GlueType F='Inh'>0</GlueType><WalkPreference F='Inh'>0</WalkPreference><BegTrigger F='No Formula'>0</BegTrigger><EndTrigger F='No Formula'>0</EndTrigger><ObjType>1</ObjType><Comment F='Inh'/><IsDropSource F='Inh'>0</IsDropSource><NoLiveDynamics F='Inh'>0</NoLiveDynamics><LocalizeMerge F='Inh'>0</LocalizeMerge><Calendar F='Inh'>0</Calendar><LangID F='Inh'>1041</LangID><ShapeKeywords F='Inh'/><DropOnPageScale F='Inh'>1</DropOnPageScale></Misc>
					<Protection><LockWidth F='Inh'>0</LockWidth><LockHeight F='Inh'>0</LockHeight><LockMoveX F='Inh'>0</LockMoveX><LockMoveY F='Inh'>0</LockMoveY><LockAspect F='Inh'>0</LockAspect><LockDelete F='Inh'>0</LockDelete><LockBegin F='Inh'>0</LockBegin><LockEnd F='Inh'>0</LockEnd><LockRotate F='Inh'>0</LockRotate><LockCrop F='Inh'>0</LockCrop><LockVtxEdit F='Inh'>0</LockVtxEdit><LockTextEdit F='Inh'>0</LockTextEdit><LockFormat F='Inh'>0</LockFormat><LockGroup F='Inh'>0</LockGroup><LockCalcWH F='Inh'>0</LockCalcWH><LockSelect F='Inh'>0</LockSelect><LockCustProp F='Inh'>0</LockCustProp></Protection>
					<vx:Protection xmlns:vx='http://schemas.microsoft.com/visio/2006/extension'><vx:LockFromGroupFormat F='Inh'>0</vx:LockFromGroupFormat><vx:LockThemeColors F='Inh'>0</vx:LockThemeColors><vx:LockThemeEffects>1</vx:LockThemeEffects></vx:Protection>
					<User NameU='CH' ID='1'><Value F='IF(TEXTWIDTH(TheText)-LeftMargin-RightMargin&gt;0.1PT,0,5)'>5</Value><Prompt F='No Formula'/></User>
					<User NameU='visVersion' ID='3'><Value>12</Value><Prompt F='No Formula'/></User>
					<Control NameU='Row_1' ID='1'><X F='Width*0.5'>0.3937007874015748</X><Y Unit='MM' F='Height-7.499999986MM'>0.4921259848031497</Y><XDyn F='Controls.Row_1'>0.3937007874015748</XDyn><YDyn Unit='MM' F='Controls.Row_1.Y'>0.4921259848031497</YDyn><XCon F='IF(OR(Height=0,Width=0),6,1)'>1</XCon><YCon>4</YCon><CanGlue>1</CanGlue><Prompt>奥行の変更</Prompt></Control>
					<!-- 背景色 -->
					<Fill><FillForegnd F="RGB(30,144,255)"/></Fill>
					<Line>
						<!-- 罫線の太さ -->
						<LineWeight>0.0138889</LineWeight>
						<!-- 罫線の色 -->
						<LineColor F="RGB(32,32,140)"/>
						<!-- 罫線の普通の線 -->
						<LinePattern>1</LinePattern>
					</Line>
					<!-- custom 文字の配置 -->
					<Control NameU='Row_2' ID='2'><X Unit='PT' F='Width*0.5'/><Y Unit='PT' F='Height*0.375'/></Control>
					<!-- custom 文字定義 -->
					<Char IX="0"><Font F="FONTTOID(&quot;Arial&quot;)">0</Font><Color F="RGB(140,32,32)"/><Style>0</Style><Size>0.138889</Size></Char>
					<Scratch IX='0'><X F='No Formula'>0</X><Y Unit='MM' F='MAX(Height-ABS(MAX(Height*0.25,Controls.Row_1.Y)),0)'>0.29527559</Y><A Unit='BOOL' F='IF(Controls.Row_1.Y&lt;Height*0,SETF(GetRef(Controls.Row_1.Y),Height*0),IF(Controls.Row_1.Y&gt;Height*1,SETF(GetRef(Controls.Row_1.Y),Height*1),FALSE))'>0</A><B F='No Formula'>0</B><C F='No Formula'>0</C><D F='No Formula'>0</D></Scratch>
					<Connection IX='0'><X F='Width*1'/><Y F='Height*0.5'/><DirX F='No Formula'>0</DirX><DirY F='No Formula'>0</DirY><Type F='No Formula'>0</Type><AutoGen F='No Formula'>0</AutoGen><Prompt F='No Formula'/></Connection>
					<Connection IX='1'><X F='Width*0.5'/><Y Unit='MM'/><DirX F='No Formula'>0</DirX><DirY F='No Formula'>0</DirY><Type F='No Formula'>0</Type><AutoGen F='No Formula'>0</AutoGen><Prompt F='No Formula'/></Connection>
					<Connection IX='2'><X F='Width*0'/><Y F='Height*0.5'/><DirX F='No Formula'>0</DirX><DirY F='No Formula'>0</DirY><Type F='No Formula'>0</Type><AutoGen F='No Formula'>0</AutoGen><Prompt F='No Formula'/></Connection>
					<Connection IX='3'><X F='Width*0.5'/><Y Unit='MM' F='Height*1-0.5*Scratch.Y1'/><DirX F='No Formula'>0</DirX><DirY F='No Formula'>0</DirY><Type F='No Formula'>0</Type><AutoGen F='No Formula'>0</AutoGen><Prompt F='No Formula'/></Connection>
					<Geom IX='0'><NoFill>0</NoFill><NoLine>0</NoLine><NoShow>0</NoShow><NoSnap F='No Formula'>0</NoSnap><MoveTo IX='1'><X F='Width*0'>0</X><Y Unit='MM' F='Height-0.5*Scratch.Y1'>0.6397637798031497</Y></MoveTo><EllipticalArcTo IX='2'><X F='Width'>0.7874015748031497</X><Y Unit='MM' F='Height-0.5*Scratch.Y1'>0.6397637798031497</Y><A Unit='DL' F='Width*0.5'>0.3937007874015748</A><B Unit='DL' F='Height*1'>0.7874015748031497</B><C Unit='DA'>0</C><D F='Width/Scratch.Y1'>2.666666671644445</D></EllipticalArcTo><EllipticalArcTo IX='3'><X F='Geometry1.X1'>0</X><Y Unit='MM' F='Geometry1.Y1'>0.6397637798031497</Y><A Unit='DL' F='Width*0.5'>0.3937007874015748</A><B Unit='MM' F='Height-Scratch.Y1'>0.4921259848031497</B><C Unit='DA'>0</C><D F='Width/Scratch.Y1'>2.666666671644445</D></EllipticalArcTo></Geom>
					<Geom IX='1'><NoFill>0</NoFill><NoLine>0</NoLine><NoShow>0</NoShow><NoSnap F='No Formula'>0</NoSnap><MoveTo IX='1'><X F='Width*0'>0</X><Y Unit='MM' F='Height-(0.5*Scratch.Y1)'>0.6397637798031497</Y></MoveTo><LineTo IX='2'><X F='Width*0'>0</X><Y Unit='MM' F='0.5*Scratch.Y1'>0.147637795</Y></LineTo><EllipticalArcTo IX='3'><X F='Width*1'>0.7874015748031497</X><Y Unit='MM' F='0.5*Scratch.Y1'>0.147637795</Y><A Unit='DL' F='Width*0.5'>0.3937007874015748</A><B Unit='MM'>0</B><C Unit='DA'>0</C><D F='Width/Scratch.Y1'>2.666666671644445</D></EllipticalArcTo><LineTo IX='4'><X F='Width*1'>0.7874015748031497</X><Y Unit='MM' F='Height-(0.5*Scratch.Y1)'>0.6397637798031497</Y></LineTo><EllipticalArcTo IX='5'><X F='Geometry2.X1'>0</X><Y Unit='MM' F='Geometry2.Y1'>0.6397637798031497</Y><A Unit='DL' F='Width*0.5'>0.3937007874015748</A><B Unit='MM' F='Height-(Scratch.Y1)'>0.4921259848031497</B><C Unit='DA'>0</C><D F='Width/Scratch.Y1'>2.666666671644445</D></EllipticalArcTo></Geom>
					<Text><cp IX='0'/></Text>
				</Shape>
			</Shapes>
		</Master>
		<Master ID='11' NameU='Dynamic connector' Name='動的コネクタ'>
			<Shapes>
				<Shape ID='5' Type='Shape'>
					<!-- オブジェクト情報をXForm1Dより -->
					<XForm><PinX F="(BeginX+EndX)/2"/><PinY F="(BeginY+EndY)/2"/><Width F='GUARD(EndX-BeginX)'/><Height F='GUARD(EndY-BeginY)'/></XForm>
					<XForm1D><BeginX>1.181102362204724</BeginX><BeginY>2.362204724409449</BeginY><EndX>2.362204724409449</EndX><EndY>1.181102362204724</EndY></XForm1D>
					<TextXForm><TxtPinX F='SETATREF(Controls.TextPosition)'>0</TxtPinX><TxtPinY F='SETATREF(Controls.TextPosition.Y)'>-1.181102362204724</TxtPinY><TxtWidth F='MAX(TEXTWIDTH(TheText),5*Char.Size)'>0.5555555555555556</TxtWidth><TxtHeight F='TEXTHEIGHT(TheText,TxtWidth)'>0.2444444444444444</TxtHeight><TxtLocPinX F='TxtWidth*0.5'>0.2777777777777778</TxtLocPinX><TxtLocPinY F='TxtHeight*0.5'>0.1222222222222222</TxtLocPinY><TxtAngle>0</TxtAngle></TextXForm>
					<Protection><LockWidth>0</LockWidth><LockHeight>1</LockHeight><LockMoveX>0</LockMoveX><LockMoveY>0</LockMoveY><LockAspect F='Inh'>0</LockAspect><LockDelete>0</LockDelete><LockBegin F='Inh'>0</LockBegin><LockEnd F='Inh'>0</LockEnd><LockRotate>0</LockRotate><LockCrop F='Inh'>0</LockCrop><LockVtxEdit>0</LockVtxEdit><LockTextEdit>0</LockTextEdit><LockFormat F='Inh'>0</LockFormat><LockGroup F='Inh'>0</LockGroup><LockCalcWH>1</LockCalcWH><LockSelect F='Inh'>0</LockSelect><LockCustProp F='Inh'>0</LockCustProp></Protection>
					<vx:Protection xmlns:vx='http://schemas.microsoft.com/visio/2006/extension'><vx:LockFromGroupFormat F='Inh'>0</vx:LockFromGroupFormat><vx:LockThemeColors>0</vx:LockThemeColors><vx:LockThemeEffects>0</vx:LockThemeEffects></vx:Protection>
					<Help><HelpTopic>Vis_SE.chm!#20000</HelpTopic><Copyright>Copyright 2001 Microsoft Corporation.	All rights reserved.</Copyright></Help>
					<Misc><NoObjHandles F='Inh'>0</NoObjHandles><NonPrinting F='Inh'>0</NonPrinting><NoCtlHandles F='Inh'>0</NoCtlHandles><NoAlignBox>1</NoAlignBox><UpdateAlignBox F='Inh'>0</UpdateAlignBox><HideText F='Inh'>0</HideText><DynFeedback>2</DynFeedback><GlueType>2</GlueType><WalkPreference F='Inh'>0</WalkPreference><BegTrigger F='No Formula'>0</BegTrigger><EndTrigger F='No Formula'>0</EndTrigger><ObjType>2</ObjType><Comment F='Inh'/><IsDropSource F='Inh'>0</IsDropSource><NoLiveDynamics>1</NoLiveDynamics><LocalizeMerge F='Inh'>0</LocalizeMerge><Calendar F='Inh'>0</Calendar><LangID F='Inh'>1041</LangID><ShapeKeywords F='Inh'/><DropOnPageScale F='Inh'>1</DropOnPageScale></Misc>
					<Layout><ShapePermeableX F='Inh'>0</ShapePermeableX><ShapePermeableY F='Inh'>0</ShapePermeableY><ShapePermeablePlace F='Inh'>0</ShapePermeablePlace><ShapeFixedCode F='Inh'>0</ShapeFixedCode><ShapePlowCode F='Inh'>0</ShapePlowCode><ShapeRouteStyle F='Inh'>0</ShapeRouteStyle><ConFixedCode F='Inh'>0</ConFixedCode><ConLineJumpCode F='Inh'>0</ConLineJumpCode><ConLineJumpStyle F='Inh'>0</ConLineJumpStyle><ConLineJumpDirX F='Inh'>0</ConLineJumpDirX><ConLineJumpDirY F='Inh'>0</ConLineJumpDirY><ShapePlaceFlip F='Inh'>0</ShapePlaceFlip><ConLineRouteExt F='Inh'>0</ConLineRouteExt><ShapeSplit F='Inh'>0</ShapeSplit><ShapeSplittable>1</ShapeSplittable></Layout>
					<vx:Layout xmlns:vx='http://schemas.microsoft.com/visio/2006/extension'><vx:ShapePlaceStyle F='Inh'>0</vx:ShapePlaceStyle></vx:Layout>
					<LayerMem><LayerMember>0</LayerMember></LayerMem>
					<Event><TheData F='No Formula'>0</TheData><TheText F='No Formula'>0</TheText><EventDblClick F='No Formula'>0</EventDblClick><EventXFMod F='No Formula'>0</EventXFMod><EventDrop F='No Formula'>0</EventDrop></Event>
					<vx:Event xmlns:vx='http://schemas.microsoft.com/visio/2006/extension'><vx:EventMultiDrop F='No Formula'>0</vx:EventMultiDrop></vx:Event>
					<Control NameU='TextPosition' ID='1'><X>0</X><Y>-1.181102362204724</Y><XDyn F='Controls.TextPosition'>0</XDyn><YDyn F='Controls.TextPosition.Y'>-1.181102362204724</YDyn><XCon F='IF(OR(STRSAME(SHAPETEXT(TheText),""),HideText),5,0)'>5</XCon><YCon>0</YCon><CanGlue>0</CanGlue><Prompt>Reposition Text</Prompt></Control>
					<Char IX='0'><Font F='Inh'>7</Font><Color F='Inh'>0</Color><Style F='Inh'>0</Style><Case F='Inh'>0</Case><Pos F='Inh'>0</Pos><FontScale F='Inh'>1</FontScale><Size F='Inh'>0.1111111111111111</Size><DblUnderline F='Inh'>0</DblUnderline><Overline F='Inh'>0</Overline><Strikethru F='Inh'>0</Strikethru><Highlight F='Inh'>0</Highlight><DoubleStrikethrough F='Inh'>0</DoubleStrikethrough><RTLText F='Inh'>0</RTLText><UseVertical F='Inh'>0</UseVertical><Letterspace F='Inh'>0</Letterspace><ColorTrans F='Inh'>0</ColorTrans><AsianFont F='Inh'>7</AsianFont><ComplexScriptFont F='Inh'>0</ComplexScriptFont><LocalizeFont F='Inh'>0</LocalizeFont><ComplexScriptSize F='Inh'>-1</ComplexScriptSize><LangID F='Inh'>1041</LangID></Char>
					<!-- 線の折れぐらいをカスタム定義 -->
					<Geom IX='0'><MoveTo IX='1'><X F="Width*0"/><Y F="Height*0"/></MoveTo><LineTo IX='2'><X F="Width*0.25"/><Y F="Height*0"/></LineTo><LineTo IX='3'><X F="Width*0.25"/><Y F="Height*1"/></LineTo><LineTo IX='4'><X F="Width*1"/><Y F="Height*1"/></LineTo></Geom>
					<!-- 背景を透過させる -->
					<Fill><FillForegnd F='Inh'>1</FillForegnd><FillBkgnd F='Inh'>0</FillBkgnd><FillPattern F='Inh'>1</FillPattern><ShdwForegnd F='Inh'>0</ShdwForegnd><ShdwBkgnd F='Inh'>1</ShdwBkgnd><ShdwPattern F='Inh'>0</ShdwPattern><FillForegndTrans>1</FillForegndTrans><FillBkgndTrans>1</FillBkgndTrans><ShdwForegndTrans F='Inh'>0</ShdwForegndTrans><ShdwBkgndTrans F='Inh'>0</ShdwBkgndTrans><ShapeShdwType F='Inh'>0</ShapeShdwType><ShapeShdwOffsetX F='Inh'>0</ShapeShdwOffsetX><ShapeShdwOffsetY F='Inh'>0</ShapeShdwOffsetY><ShapeShdwObliqueAngle F='Inh'>0</ShapeShdwObliqueAngle><ShapeShdwScaleFactor F='Inh'>1</ShapeShdwScaleFactor></Fill>
				</Shape>
			</Shapes>
		</Master>
	</Masters>
	<Pages>
		<Page ID="0">
			<PageSheet>
				<PageProps>
					<!-- 1+3*3 -->
					<PageWidth>10</PageWidth>
					<PageHeight>10</PageHeight>
				</PageProps>
			</PageSheet>
			<Shapes>
				<!-- Object															-->
				<Shape ID="1" Master='0'>
					<XForm><PinX F='2+3*0'/><PinY F='1'/></XForm>
					<Text>BL</Text>
				</Shape>
				<Shape ID="2" Master='1'>
					<XForm><PinX F='2+3*1'/><PinY F='2'/></XForm>
					<Text>DataBase</Text>
				</Shape>
				<Shape ID="3" Master='1'>
					<XForm><PinX F='2+3*1'/><PinY F='1'/></XForm>
					<Text>DataBase</Text>
				</Shape>
				<Shape ID="4" Master='0'>
					<XForm><PinX F='2+3*2'/><PinY F='1'/></XForm>
					<Text>BL2</Text>
				</Shape>
				<!-- Edge																 -->
				<Shape ID='10' Master='11'>
					<XForm1D>
						<BeginX F="PAR(PNT(Sheet.1!Connections.X1,Sheet.1!Connections.Y1))"/>
						<BeginY F="PAR(PNT(Sheet.1!Connections.X1,Sheet.1!Connections.Y1))"/>
						<EndX F="PAR(PNT(Sheet.2!Connections.X3,Sheet.2!Connections.Y1))"/>
						<EndY F="PAR(PNT(Sheet.2!Connections.X3,Sheet.2!Connections.Y1))"/>
					</XForm1D>
				</Shape>
				<Shape ID='11' Master='11'>
					<XForm1D>
						<BeginX F="PAR(PNT(Sheet.1!Connections.X1,Sheet.1!Connections.Y1))"/>
						<BeginY F="PAR(PNT(Sheet.1!Connections.X1,Sheet.1!Connections.Y1))"/>
						<EndX F="PAR(PNT(Sheet.3!Connections.X3,Sheet.3!Connections.Y1))"/>
						<EndY F="PAR(PNT(Sheet.3!Connections.X3,Sheet.3!Connections.Y1))"/>
					</XForm1D>
				</Shape>
				<Shape ID='12' Master='11'>
					<XForm1D>
						<BeginX F="PAR(PNT(Sheet.2!Connections.X1,Sheet.2!Connections.Y1))"/>
						<BeginY F="PAR(PNT(Sheet.2!Connections.X1,Sheet.2!Connections.Y1))"/>
						<EndX F="PAR(PNT(Sheet.4!Connections.X3,Sheet.4!Connections.Y1))"/>
						<EndY F="PAR(PNT(Sheet.4!Connections.X3,Sheet.4!Connections.Y1))"/>
					</XForm1D>
				</Shape>
				<Shape ID='13' Master='11'>
					<XForm1D>
						<BeginX F="PAR(PNT(Sheet.3!Connections.X1,Sheet.3!Connections.Y1))"/>
						<BeginY F="PAR(PNT(Sheet.3!Connections.X1,Sheet.3!Connections.Y1))"/>
						<EndX F="PAR(PNT(Sheet.4!Connections.X3,Sheet.4!Connections.Y1))"/>
						<EndY F="PAR(PNT(Sheet.4!Connections.X3,Sheet.4!Connections.Y1))"/>
					</XForm1D>
				</Shape>
			</Shapes>
		</Page>
	</Pages>
</VisioDocument>
```
![sample1_3.png](https://qiita-image-store.s3.amazonaws.com/0/82321/b5227569-cfb9-9554-e323-b5deab2043fd.png)

おわりに...
================================================
割りとXMLをparseすることはできそうですが、一方でこれを毎度生成するのはツライなーっと感じました。
なので、元気がでたらblockdiagのparser等々を利用して、同じAPIでblockdiagのファイル形式からvisio出力できるようにしたいと夢見ています。