title: How to parse XSD file with Python
body: <p>How can I parse the XSD below to get the 3 names inside <code>&lt;xsd:complexType name=&quot;Register-Type&quot; abstract=&quot;true&quot;&gt;</code></p>
  <p>I would like to get the names &quot;measures&quot;, &quot;description&quot;, and &quot;notes&quot; and put each one in a column on the csv (no other information, just these 3 names to show up as headers for now).</p>
  <p>I am trying to use lxml but I do not know how to go into the specific complexType tag that I want.</p>
  <p>Below is the XSD file:</p>
  <pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
  &lt;xsd:schema targetNamespace=&quot;urn:nortel:namespaces:mcp:oms&quot; xmlns:mcp=&quot;urn:nortel:namespaces:mcp:oms&quot; xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot; xmlns:parm=&quot;http://www.nortelnetworks.com/namespaces/mcp/params&quot; xmlns:xmllib=&quot;http://www.w3.org/2001/03/XMLSchema/TypeLibrary&quot; elementFormDefault=&quot;qualified&quot; attributeFormDefault=&quot;unqualified&quot;&gt;
  
          &lt;xsd:import namespace=&quot;http://www.nortelnetworks.com/namespaces/mcp/params&quot; schemaLocation=&quot;../parms/basedefs.xsd&quot;/&gt;
          &lt;xsd:import namespace=&quot;http://www.w3.org/2001/03/XMLSchema/TypeLibrary&quot; schemaLocation=&quot;../w3org/TypeLibrary.xsd&quot;/&gt;
          
          &lt;xsd:simpleType name=&quot;Precollector-Type&quot;&gt;
                  &lt;xsd:annotation&gt;
                          &lt;xsd:documentation xml:lang=&quot;en&quot;&gt;
                                  This enumerates the types of pre-collector interfaces a helper class
                                  will implement.
                          &lt;/xsd:documentation&gt;
                  &lt;/xsd:annotation&gt;
                  &lt;xsd:restriction base=&quot;xsd:string&quot;&gt;
                          &lt;xsd:enumeration value=&quot;centurySecond&quot;/&gt;
                          &lt;xsd:enumeration value=&quot;liveQuery&quot;/&gt;
                          &lt;xsd:enumeration value=&quot;transferPeriod&quot;/&gt;
                  &lt;/xsd:restriction&gt;
          &lt;/xsd:simpleType&gt;
          
          &lt;xsd:simpleType name=&quot;Register-Name-Type&quot;&gt;
                  &lt;xsd:annotation&gt;
                          &lt;xsd:documentation xml:lang=&quot;en&quot;&gt;
                                  This type defines the pattern for a allowed OM register name.
                          &lt;/xsd:documentation&gt;
                  &lt;/xsd:annotation&gt;
                  &lt;xsd:restriction base=&quot;xsd:string&quot;&gt;
                          &lt;xsd:minLength value=&quot;1&quot;/&gt;
                          &lt;xsd:pattern value=&quot;[a-zA-Z_][a-zA-Z0-9_]*&quot;/&gt;
                  &lt;/xsd:restriction&gt;
          &lt;/xsd:simpleType&gt;
          
          &lt;xsd:simpleType name=&quot;Class-Name-Type&quot;&gt;
                  &lt;xsd:annotation&gt;
                          &lt;xsd:documentation xml:lang=&quot;en&quot;&gt;
                                  This type defines the pattern for a allowed class name.
                          &lt;/xsd:documentation&gt;
                  &lt;/xsd:annotation&gt;
                  &lt;xsd:restriction base=&quot;xsd:string&quot;&gt;
                          &lt;xsd:minLength value=&quot;1&quot;/&gt;
                          &lt;xsd:pattern value=&quot;[a-zA-Z][a-zA-Z0-9_]*&quot;/&gt;
                  &lt;/xsd:restriction&gt;
          &lt;/xsd:simpleType&gt;
  
          &lt;xsd:simpleType name=&quot;Package-Name-Type&quot;&gt;
                  &lt;xsd:annotation&gt;
                          &lt;xsd:documentation xml:lang=&quot;en&quot;&gt;
                                  This type defines the pattern for a allowed package name.
                          &lt;/xsd:documentation&gt;
                  &lt;/xsd:annotation&gt;
                  &lt;xsd:restriction base=&quot;xsd:string&quot;&gt;
                          &lt;xsd:minLength value=&quot;1&quot;/&gt;
                          &lt;xsd:pattern value=&quot;([a-zA-Z][a-zA-Z0-9_]*)([.][a-zA-Z][a-zA-Z0-9_]*)*&quot;/&gt;
                  &lt;/xsd:restriction&gt;
          &lt;/xsd:simpleType&gt;
          
          &lt;xsd:simpleType name=&quot;Group-Name-Type&quot;&gt;
                  &lt;xsd:annotation&gt;
                          &lt;xsd:documentation xml:lang=&quot;en&quot;&gt;
                                  This type defines the pattern for a allowed OM group name.
                          &lt;/xsd:documentation&gt;
                  &lt;/xsd:annotation&gt;
                  &lt;xsd:restriction base=&quot;xsd:string&quot;&gt;
                          &lt;xsd:minLength value=&quot;1&quot;/&gt;
                          &lt;xsd:maxLength value=&quot;32&quot;/&gt;
                          &lt;xsd:pattern value=&quot;[a-zA-Z][a-zA-Z0-9_]*&quot;/&gt;
                  &lt;/xsd:restriction&gt;
          &lt;/xsd:simpleType&gt;
  
          &lt;xsd:complexType name=&quot;NE-List-Type&quot;&gt;
              &lt;xsd:sequence&gt;
                  &lt;xsd:element name=&quot;ne&quot; minOccurs=&quot;1&quot; maxOccurs=&quot;unbounded&quot;&gt;
                      &lt;xsd:simpleType&gt;
                          &lt;xsd:restriction base=&quot;parm:NE-Base-Type&quot;/&gt;
                      &lt;/xsd:simpleType&gt;
                  &lt;/xsd:element&gt;
              &lt;/xsd:sequence&gt;
          &lt;/xsd:complexType&gt;
  
          &lt;xsd:element name=&quot;list&quot; type=&quot;mcp:NE-List-Type&quot;&gt;
                  &lt;xsd:unique name=&quot;UniqueNEinList&quot;&gt;
                      &lt;xsd:selector xpath=&quot;mcp:ne&quot;/&gt;
                      &lt;xsd:field xpath=&quot;.&quot;/&gt;
                  &lt;/xsd:unique&gt;
          &lt;/xsd:element&gt;
  
          &lt;xsd:complexType name=&quot;OM-NE-List-Type&quot;&gt;
                  &lt;xsd:annotation&gt;
                          &lt;xsd:documentation xml:lang=&quot;en&quot;&gt;
                                  This type defines the way that you define which NE types
                                  will generate a given OM group.  It uses the NE base type
                                  that we use for our engineering and configuration parameters.
                          &lt;/xsd:documentation&gt;
                  &lt;/xsd:annotation&gt;
                  &lt;xsd:choice&gt;
                          &lt;xsd:element name=&quot;all&quot;&gt;
                                  &lt;xsd:complexType/&gt;
                          &lt;/xsd:element&gt;
                          &lt;xsd:element ref=&quot;mcp:list&quot;/&gt;
                  &lt;/xsd:choice&gt;
          &lt;/xsd:complexType&gt;
          
          &lt;xsd:complexType name=&quot;OM-Installation-Type&quot;&gt;
              &lt;xsd:sequence&gt;
                  &lt;xsd:element name=&quot;package&quot; type=&quot;mcp:Package-Name-Type&quot;/&gt;
                  &lt;xsd:element ref=&quot;mcp:list&quot;/&gt;
              &lt;/xsd:sequence&gt;
          &lt;/xsd:complexType&gt;
  
          &lt;xsd:complexType name=&quot;Register-Type&quot; abstract=&quot;true&quot;&gt;
                  &lt;xsd:sequence&gt;
                          &lt;xsd:element name=&quot;measures&quot; type=&quot;xmllib:text&quot;/&gt;
                          &lt;xsd:element name=&quot;description&quot; type=&quot;xmllib:text&quot;/&gt;
                          &lt;xsd:element name=&quot;notes&quot; type=&quot;xmllib:text&quot; minOccurs=&quot;0&quot;/&gt;
                  &lt;/xsd:sequence&gt;
                  &lt;xsd:attribute name=&quot;name&quot; type=&quot;mcp:Register-Name-Type&quot; use=&quot;required&quot;/&gt;
          &lt;/xsd:complexType&gt;
          
          &lt;xsd:complexType name=&quot;Counter-Type&quot;&gt;
                  &lt;xsd:complexContent&gt;
                          &lt;xsd:extension base=&quot;mcp:Register-Type&quot;/&gt;
                  &lt;/xsd:complexContent&gt;
          &lt;/xsd:complexType&gt;
          
          &lt;xsd:complexType name=&quot;Usage-Type&quot;&gt;
                  &lt;xsd:complexContent&gt;
                          &lt;xsd:extension base=&quot;mcp:Register-Type&quot;&gt;
                                  &lt;xsd:attribute name=&quot;hasThresholds&quot; type=&quot;xsd:boolean&quot; default=&quot;false&quot;/&gt;
                          &lt;/xsd:extension&gt;
                  &lt;/xsd:complexContent&gt;
          &lt;/xsd:complexType&gt;
          
          &lt;xsd:complexType name=&quot;LowWaterGauge-Type&quot;&gt;
                  &lt;xsd:complexContent&gt;
                          &lt;xsd:extension base=&quot;mcp:Register-Type&quot;/&gt;
                  &lt;/xsd:complexContent&gt;
          &lt;/xsd:complexType&gt;
          
          &lt;xsd:complexType name=&quot;HighWaterGauge-Type&quot;&gt;
                  &lt;xsd:complexContent&gt;
                          &lt;xsd:extension base=&quot;mcp:Register-Type&quot;/&gt;
                  &lt;/xsd:complexContent&gt;
          &lt;/xsd:complexType&gt;
          
          &lt;xsd:complexType name=&quot;Gauge-Ref-Type&quot;&gt;
                  &lt;xsd:attribute name=&quot;ref&quot; type=&quot;mcp:Register-Name-Type&quot; use=&quot;required&quot;/&gt;
          &lt;/xsd:complexType&gt;
          
          &lt;xsd:complexType name=&quot;Multi-Gauge-Ref-Type&quot;&gt;
                  &lt;xsd:attribute name=&quot;lwref&quot; type=&quot;mcp:Register-Name-Type&quot; use=&quot;required&quot;/&gt;
                  &lt;xsd:attribute name=&quot;hwref&quot; type=&quot;mcp:Register-Name-Type&quot; use=&quot;required&quot;/&gt;
          &lt;/xsd:complexType&gt;
          
          &lt;xsd:complexType name=&quot;WaterMark-Type&quot;&gt;
                  &lt;xsd:complexContent&gt;
                          &lt;xsd:extension base=&quot;mcp:Register-Type&quot;&gt;
                                  &lt;xsd:choice&gt;
                                          &lt;xsd:element name=&quot;lwg&quot; type=&quot;mcp:Gauge-Ref-Type&quot;/&gt;
                                          &lt;xsd:element name=&quot;hwg&quot; type=&quot;mcp:Gauge-Ref-Type&quot;/&gt;
                                          &lt;xsd:element name=&quot;bwg&quot; type=&quot;mcp:Multi-Gauge-Ref-Type&quot;/&gt;
                                  &lt;/xsd:choice&gt;
                          &lt;/xsd:extension&gt;
                  &lt;/xsd:complexContent&gt;
          &lt;/xsd:complexType&gt;
          
          &lt;xsd:element name=&quot;register&quot; type=&quot;mcp:Register-Type&quot; abstract=&quot;true&quot;/&gt;
          &lt;xsd:element name=&quot;counter&quot; type=&quot;mcp:Counter-Type&quot; substitutionGroup=&quot;mcp:register&quot;/&gt;
          &lt;xsd:element name=&quot;usage&quot; type=&quot;mcp:Usage-Type&quot; substitutionGroup=&quot;mcp:register&quot;/&gt;
          &lt;xsd:element name=&quot;lwGauge&quot; type=&quot;mcp:LowWaterGauge-Type&quot; substitutionGroup=&quot;mcp:register&quot;/&gt;
          &lt;xsd:element name=&quot;hwGauge&quot; type=&quot;mcp:HighWaterGauge-Type&quot; substitutionGroup=&quot;mcp:register&quot;/&gt;
          &lt;xsd:element name=&quot;waterMark&quot; type=&quot;mcp:WaterMark-Type&quot; substitutionGroup=&quot;mcp:register&quot;/&gt;
          
          &lt;xsd:complexType name=&quot;Helper-Class-Type&quot;&gt;
                  &lt;xsd:sequence&gt;
                          &lt;xsd:element name=&quot;package&quot; type=&quot;mcp:Package-Name-Type&quot;/&gt;
                          &lt;xsd:element name=&quot;class&quot; type=&quot;mcp:Class-Name-Type&quot;/&gt;
                          &lt;xsd:element name=&quot;collector&quot; type=&quot;mcp:Precollector-Type&quot; minOccurs=&quot;1&quot; maxOccurs=&quot;unbounded&quot; /&gt;
                  &lt;/xsd:sequence&gt;
          &lt;/xsd:complexType&gt;
          
          &lt;xsd:complexType name=&quot;Row-Type&quot;&gt;
                  &lt;xsd:sequence&gt;
                          &lt;xsd:element name=&quot;package&quot; type=&quot;mcp:Package-Name-Type&quot;/&gt;
                          &lt;xsd:element name=&quot;class&quot; type=&quot;mcp:Class-Name-Type&quot;/&gt;
                          &lt;xsd:element ref=&quot;mcp:register&quot; maxOccurs=&quot;unbounded&quot;/&gt;
                          &lt;!-- Note that merely having a precollector with a centurySecond element is enough to indicate that you require   --&gt;
                          &lt;!-- a century second scan, so there's no additional markup on the group to show that. --&gt;
                          &lt;xsd:element name=&quot;precollector&quot; minOccurs=&quot;0&quot; type=&quot;mcp:Helper-Class-Type&quot;&gt;
                                  &lt;xsd:unique name=&quot;NoDuplicatePrecollectorTypes&quot;&gt;
                                  &lt;xsd:selector xpath=&quot;mcp:collector&quot;/&gt;
                                  &lt;xsd:field xpath=&quot;.&quot;/&gt;
                                  &lt;/xsd:unique&gt;
                          &lt;/xsd:element&gt;
                  &lt;/xsd:sequence&gt;
          &lt;/xsd:complexType&gt;
          
          &lt;xsd:complexType name=&quot;Group-Description-Type&quot;&gt;
                  &lt;xsd:sequence&gt;
                          &lt;xsd:element name=&quot;description&quot; type=&quot;xmllib:text&quot;/&gt;
                          &lt;xsd:element name=&quot;rowKey&quot; type=&quot;xmllib:text&quot;/&gt;
                  &lt;/xsd:sequence&gt;
          &lt;/xsd:complexType&gt;
          
          &lt;xsd:complexType name=&quot;Group-Type&quot;&gt;
                  &lt;xsd:sequence&gt;
                          &lt;xsd:element name=&quot;name&quot; type=&quot;mcp:Group-Name-Type&quot;/&gt;
                          &lt;xsd:element name=&quot;row&quot; type=&quot;mcp:Row-Type&quot;&gt;
                                  &lt;xsd:unique name=&quot;uniqueRegisterNameInRow&quot;&gt;
                                          &lt;xsd:selector xpath=&quot;mcp:counter|mcp:usage|mcp:lwGauge|mcp:hwGauge|mcp:waterMark&quot;/&gt;
                                          &lt;xsd:field xpath=&quot;@name&quot;/&gt;
                                  &lt;/xsd:unique&gt;
                                  &lt;xsd:key name=&quot;lwgauge-name&quot;&gt;
                                          &lt;xsd:selector xpath=&quot;mcp:lwGauge&quot;/&gt;
                                          &lt;xsd:field xpath=&quot;@name&quot;/&gt;
                                  &lt;/xsd:key&gt;
                                  &lt;xsd:key name=&quot;hwgauge-name&quot;&gt;
                                          &lt;xsd:selector xpath=&quot;mcp:hwGauge&quot;/&gt;
                                          &lt;xsd:field xpath=&quot;@name&quot;/&gt;
                                  &lt;/xsd:key&gt;
                                  &lt;xsd:key name=&quot;multi-gauge-name&quot;&gt;
                                          &lt;xsd:selector xpath=&quot;mcp:waterMark/mcp:bwg&quot;/&gt;
                                          &lt;xsd:field xpath=&quot;@lwref&quot;/&gt;
                                          &lt;xsd:field xpath=&quot;@hwref&quot;/&gt;
                                  &lt;/xsd:key&gt;
                                  &lt;xsd:key name=&quot;unique-lwg-ref&quot;&gt;
                                          &lt;xsd:selector xpath=&quot;mcp:waterMark/mcp:lwg&quot;/&gt;
                                          &lt;xsd:field xpath=&quot;@ref&quot;/&gt;
                                  &lt;/xsd:key&gt;
                                  &lt;xsd:key name=&quot;unique-hwg-ref&quot;&gt;
                                          &lt;xsd:selector xpath=&quot;mcp:waterMark/mcp:hwg&quot;/&gt;
                                          &lt;xsd:field xpath=&quot;@ref&quot;/&gt;
                                  &lt;/xsd:key&gt;
                                  &lt;xsd:key name=&quot;unique-bwg-lwref&quot;&gt;
                                          &lt;xsd:selector xpath=&quot;mcp:waterMark/mcp:bwg&quot;/&gt;
                                          &lt;xsd:field xpath=&quot;@lwref&quot;/&gt;
                                  &lt;/xsd:key&gt;
                                  &lt;xsd:key name=&quot;unique-bwg-hwref&quot;&gt;
                                          &lt;xsd:selector xpath=&quot;mcp:waterMark/mcp:bwg&quot;/&gt;
                                          &lt;xsd:field xpath=&quot;@hwref&quot;/&gt;
                                  &lt;/xsd:key&gt;
                                  &lt;!-- Unfortunately, I cannot figure out a way to --&gt;
                                  &lt;!-- prevent someone from referencing a gauge    --&gt;
                                  &lt;!-- simultaneously from a l/hwg and bwg element --&gt;
                                  &lt;!-- without using something like schematron.    --&gt;
                                  &lt;xsd:keyref name=&quot;lwg-ref&quot; refer=&quot;mcp:lwgauge-name&quot;&gt;
                                          &lt;xsd:selector xpath=&quot;mcp:waterMark/mcp:lwg&quot;/&gt;
                                          &lt;xsd:field xpath=&quot;@ref&quot;/&gt;
                                  &lt;/xsd:keyref&gt;
                                  &lt;xsd:keyref name=&quot;hwg-ref&quot; refer=&quot;mcp:hwgauge-name&quot;&gt;
                                          &lt;xsd:selector xpath=&quot;mcp:waterMark/mcp:hwg&quot;/&gt;
                                          &lt;xsd:field xpath=&quot;@ref&quot;/&gt;
                                  &lt;/xsd:keyref&gt;
                                  &lt;xsd:keyref name=&quot;bwg-lwref&quot; refer=&quot;mcp:lwgauge-name&quot;&gt;
                                          &lt;xsd:selector xpath=&quot;mcp:waterMark/mcp:bwg&quot;/&gt;
                                          &lt;xsd:field xpath=&quot;@lwref&quot;/&gt;
                                  &lt;/xsd:keyref&gt;
                                  &lt;xsd:keyref name=&quot;bwg-hwref&quot; refer=&quot;mcp:hwgauge-name&quot;&gt;
                                          &lt;xsd:selector xpath=&quot;mcp:waterMark/mcp:bwg&quot;/&gt;
                                          &lt;xsd:field xpath=&quot;@hwref&quot;/&gt;
                                  &lt;/xsd:keyref&gt;
                          &lt;/xsd:element&gt;
                          &lt;xsd:element name=&quot;documentation&quot; type=&quot;mcp:Group-Description-Type&quot;/&gt;
                          &lt;xsd:element name=&quot;generatedOn&quot; type=&quot;mcp:OM-NE-List-Type&quot;/&gt;
                  &lt;/xsd:sequence&gt;
                  &lt;xsd:attribute name=&quot;traffic&quot; type=&quot;xsd:boolean&quot; default=&quot;false&quot;/&gt;
                  &lt;xsd:attribute name=&quot;neLevel&quot; type=&quot;xsd:boolean&quot; default=&quot;false&quot;&gt;
                      &lt;xsd:annotation&gt;
                          &lt;xsd:documentation&gt;
                              This attribute is set to true for those OM groups that measure
                              something that can only be counted on the active network element
                              instance.  Many call-related counts require this attribute to
                              be set to &quot;true&quot; to ensure that any averages are calculated
                              correctly.
                          &lt;/xsd:documentation&gt;
                      &lt;/xsd:annotation&gt;
                  &lt;/xsd:attribute&gt;
          &lt;/xsd:complexType&gt;
          
          &lt;xsd:element name=&quot;omGroups&quot;&gt;
                  &lt;xsd:annotation&gt;
                          &lt;xsd:documentation xml:lang=&quot;en&quot;&gt;
                                  Each OM row class can belong to one and only one OM group.
                                  That is more restrictive than the underlying framework, but
                                  it would be difficult to impossible to make the documentation 
                                  markup work since the meaning of the fields would change depending on 
                                  the OM group to which the class belonged.
                          &lt;/xsd:documentation&gt;
                  &lt;/xsd:annotation&gt;
                  &lt;xsd:complexType&gt;
                          &lt;xsd:sequence&gt;
                              &lt;xsd:element name=&quot;install&quot; type=&quot;mcp:OM-Installation-Type&quot; minOccurs=&quot;1&quot; maxOccurs=&quot;unbounded&quot;/&gt;
                              &lt;xsd:element name=&quot;group&quot; type=&quot;mcp:Group-Type&quot; minOccurs=&quot;1&quot; maxOccurs=&quot;unbounded&quot;/&gt;
                          &lt;/xsd:sequence&gt;
                  &lt;/xsd:complexType&gt;
                  &lt;!-- Each OM group name must be unique --&gt;
                  &lt;xsd:unique name=&quot;uniqueGroupName&quot;&gt;
                          &lt;xsd:selector xpath=&quot;mcp:group&quot;/&gt;
                          &lt;xsd:field xpath=&quot;mcp:name&quot;/&gt;
                  &lt;/xsd:unique&gt;
                  &lt;!-- Each OM row class can belong to one and only one OM group.            --&gt;
                  &lt;!-- That is more restrictive than the underlying framework, but           --&gt;
                  &lt;!-- it would be difficult to impossible to make the documentation         --&gt;
                  &lt;!-- markup work since the meaning of the fields would change depending on --&gt;
                  &lt;!-- the OM group to which the class belonged.                             --&gt;
                  &lt;xsd:unique name=&quot;uniqueRowClass&quot;&gt;
                          &lt;xsd:selector xpath=&quot;mcp:group/mcp:row&quot;/&gt;
                          &lt;xsd:field xpath=&quot;mcp:package&quot;/&gt;
                          &lt;xsd:field xpath=&quot;mcp:class&quot;/&gt;
                  &lt;/xsd:unique&gt;
          &lt;/xsd:element&gt;
  &lt;/xsd:schema&gt;
  
  
  </code></pre>
  <p>What I tried</p>
  <pre><code>from xml.etree import ElementTree
  import csv
  
  
  tree = ElementTree.parse('Omschema.xsd')
  
  sitescope_data = open('Out.csv', 'w', newline='', encoding='utf-8')
  csvwriter = csv.writer(sitescope_data)
  
  #Create all needed columns here in order and writes them to excel file
  
  def recurse(root):
      for child in root:
          recurse(child)
          print(child.tag)
  
      for event in root.findall('{http://www.w3.org/2001/XMLSchema}complexType'):
          event_data = []
          event_id = event.find('{http://www.w3.org/2001/XMLSchema}sequence')
          if event_id != None:
              event_id = event_id.text
          event_data.append(event_id)
  
          csvwriter.writerow(event_data)
  
  root = tree.getroot()
  recurse(root)
  sitescope_data.close()
  
  </code></pre>