views:

221

answers:

0

I'm trying to transform an XML Schema document and extract a list of all leaf element names and the path of their parent elements, i.e. the names of each element that ref's the current element, and the element that ref's that one, on up to only element that's not referred to by another ref attribute. I'm not getting anywhere, so I don't have even partially-working code to share as a starting point. Here's a small fragment of source and the desired output:

source:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema 
    targetNamespace="http://my.custom.namespace/Ops" 
    xmlns:my="http://my.custom.namespace/Ops"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
>
    <xsd:element name="Ops"> <!-- no element in the schema has an @ref="my:Ops"-->
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="my:Control" minOccurs="0"/> <!-- child of Ops -->
                <xsd:element ref="my:ProjInfo" minOccurs="0"/>
                <!-- ... -->
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="Control"> <!-- all other elements have (exactly one) @ref= to them -->
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="my:CurrViewNm" minOccurs="0"/>
                <xsd:element ref="my:CurrUser" minOccurs="0"/>
                <!-- ... -->
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="CurrViewNm" type="xsd:string"/>
    <xsd:element name="CurrUser" type="xsd:string"/>
    <!-- ... -->
    <xsd:element name="ProjInfo">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="my:Proj_Id" minOccurs="0"/>
                <xsd:element ref="my:Proj_SiteUrl" minOccurs="0"/>
                <xsd:element ref="my:ServiceTypeNotesSection" minOccurs="0"/>
                <!-- ... -->
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="Proj_Id" type="xsd:string"/>
    <xsd:element name="Proj_SiteUrl" type="xsd:anyURI"/>
    <xsd:element name="ServiceTypeNotesSection">    <!-- not a leaf node, don't list in output -->
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="my:ServiceTypeNote" minOccurs="0"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="ServiceTypeNote" type="xsd:string"/>
    <!-- ... -->
</xsd:schema>

output:

Schema: Ops {
    Categories: {    // <-- lists first descendant  xsd:element s of Ops
        Member: Control     [Path: "/my:Ops/my:Control"];
        Member: ProjInfo    [Path: "/my:Ops/my:ProjInfo"];
        ...
    }    
    // for each first descendant xsd:element of Ops,
    // list all leaf node elements, leave out intermediate descendants
    Category: Control {  
        Member: CurrViewNm  [Path: "/my:Ops/my:Control/my:CurrViewNm"];
        Member: CurrUser    [Path: "/my:Ops/my:Control/my:CurrUser"];
        ...
    }
    Category: ProjInfo  {   
        Member: ProjId      [Path: "/my:Ops/my:ProjInfo/my:ProjId"];
        Member: ProjSiteUrl [Path: "/my:Ops/my:ProjInfo/my:ProjSiteUrl"];
        // next comes a grandchild leaf node; 
        // don't make a Member for its parent ServiceTypeNotesSection
        Member: ServiceTypeNote [Path: "/my:Ops/my:ProjInfo/my:ServiceTypeNotesSection/my:ServiceTypeNote"];
        ...
    }
}

I'm having trouble everywhere. Some specific problems:

  1. How to find Ops, the xsd:element that has no ref's to it.
  2. For the leaf nodes, how to construct the path up to Ops
  3. How to group those leaf nodes under Ops' direct child xsd:elements

Any help appreciated -- solving even one of these problems will be a boost!