Search code examples
c#xmlvisio

Where are Visio Master Shape properties stored?


I have a program that parses the XML data of a Visio file. In this file there is a grouped shape consisting of several master shapes. Like so: Connector X999
Each shape has a Property called Pin

Pin 1 of connector
Pin 1 is the default value saved in the master shape. When I unzip the Visio file and look at the XML data, the "Pin" property will not show up on pin 1, but it will be there for all the other pins.

<PageContents xmlns="http://schemas.microsoft.com/office/visio/2012/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xml:space="preserve">
    <Shapes>
        <Shape ID="2010" Type="Group" LineStyle="7" FillStyle="7" TextStyle="7" UniqueID="{B849B0B2-94FC-4CC7-843F-6A55BDBD37E6}">
            <Cell N="PinX" V="8.484814432615094"/>
            <...etc>
            <Section N="Property">
                <Row N="REF">
                    <Cell N="Value" V="X999" U="STR"/>
                    <...etc>
                </Row>
            </Section>
            <Shapes>
                <Shape ID="2" NameU="Pin.1994" IsCustomNameU="1" Name="Pin.1994" IsCustomName="1" Type="Group" Master="126" UniqueID="{216A72DB-F8E9-4C30-9C34-DE9A8448552B}">
                    <Cell N="PinX" V="0.07874015748031506" F="Sheet.1!Width*0.5"/>
                    <...etc>
                    <Shapes>
                        <Text callout and background shapes>
                    </Shapes>
                </Shape>
                <Shape ID="6" NameU="Pin.2002" IsCustomNameU="1" Name="Pin.2002" IsCustomName="1" Type="Group" Master="126">
                    <Cell N="PinX" V="0.07874015748031506" F="Sheet.1!Width*0.5"/>
                    <...etc>
                    <Section N="Property">
                        <Row N="Pin">
                            <Cell N="Value" V="2" U="STR"/>
                        </Row>
                    </Section>
                    <Shapes>
                        <Text callout and background shapes>
                    </Shapes>
                </Shape>
            </Shapes>
        </Shape>
    </Shapes>
</PageContents>

If I rename the "Pin" property to anything other than "1" the property will show up just like it does on Pin 2. I thought this was because it was stored in the Master Shape, but there is no "Property" tag in the master file either.

<MasterContents xmlns="http://schemas.microsoft.com/office/visio/2012/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xml:space="preserve">
    <Shapes>
        <Shape ID="5" Type="Group" LineStyle="0" FillStyle="0" TextStyle="0" UniqueID="{F811FFC2-FDBC-4EFF-97CF-13F5FFBC677C}">
            <Cell N="PinX" V="0"/>
            <...etc>
        <Section N="User">...</Section>
        <Section N="Geometry">...</Section>
        <Shapes>
            <Shape ID="6" NameU="Text callout" IsCustomNameU="1" Name="Text callout" IsCustomName="1" Type="Group" LineStyle="3" FillStyle="3" TextStyle="3" UniqueID="{4CF654FB-78A6-413C-A551-70A86FC63644}">...</Shape>
        </Shapes>
    </Shapes>
</MasterContents>

Since Visio is displaying the value it must get the property name and value from somewhere but i have no idea where it does that.

When i parse the file i look for the "Pin" property and extract data from other properties that are in the shape, but when the "Pin" property is not present it will skip all that information for every Pin 1 in the document.

I will attach the complete xml files here if anyone wants to have a look at them.

Property renamed to "1 "

Property missing

Master126

*Edit: Zipfile with all XML files

*Edit2: VSDX file


Solution

  • Thanks for the vsdx, that's helpful.

    As you highlighted, the Pin Shape Data row in 'Pin1' shape doesn't show up in the instance shape xml (PageContents) as it is an inherited value from its master. The other two shapes, having local values, are reflected within the instance xml.

    I think the problem you're having is you're looking at the wrong master and so not finding the data you're after.

    The way to trace this back is if you look at the page xml (page1.xml) you'll see that the Pin shape is based on master id '6':

    [Note - I've cut out quite a lot of the xml in the following snippets to give a clearer picture of the structure for the file.]

    <PageContents>
        <Shapes>
            <Shape ID='17' Type='Group' LineStyle='7' FillStyle='7' TextStyle='7'>
                <Shapes>
                    <Shape ID='5' NameU='Pin' Name='Pin' Type='Group' Master='6'>
    

    Now you can look in the masters collection (masters.xml) and will see that the master with an ID attribute of 6 (the 'Pin' master) has a rel id of 'rId2':

    <Masters>
        <Master ID='2' NameU='Dynamic connector' IsCustomNameU='1' Name='Dynamic connector' IsCustomName='1'>
            <Rel r:id='rId1'/>
        </Master>
        <Master ID='6' NameU='Pin' IsCustomNameU='1' Name='Pin' IsCustomName='1'>
            <Rel r:id='rId2'/>
        </Master>
    

    Now you've got the correct rel id you and lookup the correct master declaration in master.xml.rels where you'll see that rel id 'rId2' points to master2.xml:

    <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
        <Relationship Id="rId3" Type="http://schemas.microsoft.com/visio/2010/relationships/master" Target="master3.xml"/>
        <Relationship Id="rId2" Type="http://schemas.microsoft.com/visio/2010/relationships/master" Target="master2.xml"/>
        <Relationship Id="rId1" Type="http://schemas.microsoft.com/visio/2010/relationships/master" Target="master1.xml"/>
        <Relationship Id="rId5" Type="http://schemas.microsoft.com/visio/2010/relationships/master" Target="master5.xml"/>
        <Relationship Id="rId4" Type="http://schemas.microsoft.com/visio/2010/relationships/master" Target="master4.xml"/>
    </Relationships>
    

    So your final stop is to head off to master2.xml where you should find that the top level shape (id 5) has a Shape Data row named 'Pin' and a value of '1':

    <MasterContents>
        <Shapes>
            <Shape ID='5' NameU='Pin.473' IsCustomNameU='1' Name='Pin.473' IsCustomName='1' Type='Group'>
                <Section N='Property'>
                    <Row N='Pin'>
                        <Cell N='Value' V='1' U='STR'/>
                        <Cell N='Prompt' V='' F='No Formula'/>
                        <Cell N='Label' V='Pin'/>
                        <Cell N='Format' V='' F='No Formula'/>
                        <Cell N='SortKey' V='' F='No Formula'/>
                        <Cell N='Type' V='0'/>
                        <Cell N='Invisible' V='0' F='No Formula'/>
                        <Cell N='Verify' V='0' F='No Formula'/>
                        <Cell N='DataLinked' V='0' F='No Formula'/>
                        <Cell N='LangID' V='sv-SE'/>
                        <Cell N='Calendar' V='0' F='No Formula'/>
                    </Row>
                </Section>
    

    I'm guessing that you're treating the vsdx as a zip and that you're missing out on the System.IO.Packaging namespace which will help you with navigating the package relationships. I'll add this link just in case: