4

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.

BlueSun
  • 3,541
  • 1
  • 18
  • 37
Kevin
  • 3,077
  • 6
  • 31
  • 77
  • Have you tried [XSD-to-PHP](https://github.com/moyarada/XSD-to-PHP)? – kjhughes Nov 03 '13 at 20:10
  • Not yet, I was hoping there was a simple way of doing this without any extra software. – Kevin Nov 03 '13 at 20:48
  • That actually isn't what I am looking for, I just want to take an xsd and print out the elements in the xsd – Kevin Nov 04 '13 at 16:13
  • "elements of the xsd" is ambiguous because the XSD is itself an XML document. Do you want all of elements names used in the XSD to define the schema, or do you want all of the element names that the XSD allows in the XML instances which it governs? Also, you really should show what you've tried by including your code here, not just a link and some prose about what you changed. You risk having your question closed otherwise. Thanks. – kjhughes Nov 04 '13 at 16:18
  • I have updated the question to try and clear things up – Kevin Nov 04 '13 at 17:30

1 Answers1

7

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.

kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • 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 – FantomX1 Sep 07 '18 at 15:05
  • @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. – kjhughes Sep 07 '18 at 15:08