Parse XSD file in PHP and display the elements in the XSD

17,608

This PHP:

<?php 

$xsdstring = <<<XML
<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="shiporder">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="orderperson" type="xs:string"/>
        <xs:element name="shipto">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="name" type="xs:string"/>
              <xs:element name="address" type="xs:string"/>
              <xs:element name="city" type="xs:string"/>
              <xs:element name="country" type="xs:string"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="item" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="title" type="xs:string"/>
              <xs:element name="note" type="xs:string" minOccurs="0"/>
              <xs:element name="quantity" type="xs:positiveInteger"/>
              <xs:element name="price" type="xs:decimal"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
      <xs:attribute name="orderid" type="xs:string" use="required"/>
    </xs:complexType>
  </xs:element>
</xs:schema>
XML;

$doc = new DOMDocument();
$doc->loadXML(mb_convert_encoding($xsdstring, 'utf-8', mb_detect_encoding($xsdstring)));
$xpath = new DOMXPath($doc);
$xpath->registerNamespace('xs', 'http://www.w3.org/2001/XMLSchema');

function echoElements($indent, $elementDef) {
  global $doc, $xpath;
  echo "<div>" . $indent . $elementDef->getAttribute('name') . "</div>\n";
  $elementDefs = $xpath->evaluate("xs:complexType/xs:sequence/xs:element", $elementDef);
  foreach($elementDefs as $elementDef) {
    echoElements($indent . "&nbsp;&nbsp;&nbsp;&nbsp;", $elementDef);
  }
}

$elementDefs = $xpath->evaluate("/xs:schema/xs:element");
foreach($elementDefs as $elementDef) {
  echoElements("", $elementDef);
}                       
?>

Yields the following output:

shiporder
    orderperson
    shipto
        name
        address
        city
        country
    item
        title
        note
        quantity
        price

as requested.

Note that this assumes a simple Russian Doll XSD design that uses the basic embedded xs:complexType/xs:sequence/ structure as is found in the provided shiporder definition and its descendant elements.

Share:
17,608
Kevin
Author by

Kevin

Updated on June 04, 2022

Comments

  • Kevin
    Kevin about 2 years

    I have an XSD schema file that I want to parse and echo the elements that it contains, also if possible to display the children each element has as well. I have seen some examples, the best of which have the example of: Convert XSD file into array in PHP

    I tried it and it gives me an empty array even after changing the xs: portion in xpaths and file location. Is there a proper way to parse an XSD file and display its elements in PHP?

    To clear up any confusion here is what I am trying to say:

    Lets say this is the XSD I am trying to load and display its elements (this comes from the link above):

    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    
    <xs:element name="shiporder">
      <xs:complexType>
        <xs:sequence>
          <xs:element name="orderperson" type="xs:string"/>
          <xs:element name="shipto">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="name" type="xs:string"/>
                <xs:element name="address" type="xs:string"/>
                <xs:element name="city" type="xs:string"/>
                <xs:element name="country" type="xs:string"/>
              </xs:sequence>
            </xs:complexType>
          </xs:element>
          <xs:element name="item" maxOccurs="unbounded">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="title" type="xs:string"/>
                <xs:element name="note" type="xs:string" minOccurs="0"/>
                <xs:element name="quantity" type="xs:positiveInteger"/>
                <xs:element name="price" type="xs:decimal"/>
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:sequence>
        <xs:attribute name="orderid" type="xs:string" use="required"/>
      </xs:complexType>
    </xs:element>
    
    </xs:schema>
    

    As we can see there is an element with the name "shiporder" and it has children which are, If I am not mistaken, "orderperson" that has type string, It also has "shipto" that has children elements that are: "name", "address", "city", "country" that are of type string.

    What I want to do is simply print out "shiporder" has children "orderperson" and "shipto" "shipto" has children "name", "address", "city", and "country".

    How can I acheve this? Should I be using the method described below?:

    <?php 
    $attributes = array(); 
    $xsdstring = "test.xsd"; 
    $XSDDOC = new DOMDocument(); 
    $XSDDOC->preserveWhiteSpace = false; 
    if ($XSDDOC->load($xsdstring)) 
    { 
        $xsdpath = new DOMXPath($XSDDOC); 
        $attributeNodes = 
                  $xsdpath-> 
                  query('//xs:element[@name="shiporder"]')
                  ->item(0); 
        foreach ($attributeNodes->childNodes as $attr) 
        { 
            $attributes[ $attr->getAttribute('value') ] = $attr->getAttribute('name'); 
        } 
        unset($xsdpath); 
    } 
    print_r($attributes); 
    ?>
    

    Hopefully this makes my question a bit clearer, as I am new to php and xml parsing.

  • FantomX1
    FantomX1 almost 6 years
    thanks works, I just don't like the global variables used there, and surprisingly that php doesn't support parsing xsd documents, as its also just a type of xml
  • kjhughes
    kjhughes almost 6 years
    @FantomX1: PHP does support parsing XSD as XML as shown in this answer. "Global" variables in a demo / code snippet shouldn't bother you; it's easy to button-up working code -- this is just a demo to get people started or unstuck.