If you are thinking of writing a web service or a client based on a WSDL, you can easily generate the code for PHP or any other language using tools likes wsdl2php or other wsdl2xxx category tools. Then you don’t need to really worry about what is the schema of the WSDL or any other finer details. But sometime it may useful to know how different schema constructs are generated in PHP level so you can have a good idea when you are using them. This post describes How inheritance is used in XML Schema and how it is mapped to PHP code from wsdl2php tool in WSF/PHP.

There are several ways that one schema type can inherit another type.  Here are some names use to refer them.

  • SimpleType Restriction – Forming simple type by restricting another simple type
  • SimpleContent Extension – Forming complex type by extending a simple type
  • ComplexContent Extension – Forming complex type by extending another complex type

Note that here the word ‘type’ always refers to a schema type.

It is not straight forward to do a one to one map from these schema structures to a PHP or some other language. But wsdl2php tool does that keeping the simplicity and preserving the original meaning. Lets see how it is done for each of the above mentioned methods of inheriting.

SimpleType Restriction

You can create a simple type by restricting some values of another simple type. Here is an example.

            <!-- derivedType from applying
              simple type restriction for xs:string -->
            <xs:simpleType name="derivedType">
                <xs:restriction base="xs:string">
                    <xs:enumeration value="a"/>
                    <xs:enumeration value="ab"/>
                    <xs:enumeration value="abc"/>
                    <xs:enumeration value="abcd"/>
                </xs:restriction>
            </xs:simpleType>

Here the derivedType is a string, but it can only have values “a”, “ab”, “abc” and “abcd”. This restriction have used the “enumeration” (which we call a facet) to restrict the possible values. You can use other facets like length, minLength, MaxLength and so on. Here are the complete list of facets in the schema specification.

So lets see hows this is mapped to a PHP code. Here we assume this type is used in an schema element called ‘input’.

    /**
     * @var string
     *     NOTE: $input should follow the following restrictions
     *     You can have one of the following value
     *     a
     *     ab
     *     abc
     *     abcd
     */
     public $input;

Note that here it does not say anything about the ‘derivedType’. Rather it says it is of type “String” which is a PHP type and in addition it has some restrictions, or rules when assigning values.

Although it could have been possible to use getters and setters to impose these rules, this uses just a comment about the rules because this way it is really easy the use the variable.

Say we have another type (say derievedType2) restricting the ‘derievedType’, that type will have the combination of restrictions of both types.

Here is the xml schema representation of the ‘derievedType2′.

            <!-- derivedType2-->
            <xs:simpleType name="derivedType2">
                <xs:restriction base="tns:derivedType">
                    <xs:maxLength value="3"/>
                    <xs:minLength value="2"/>
                </xs:restriction>
            </xs:simpleType>

And if input2 have that type, the php code will look like this, (Note that it has the combination of rules).

    /**
     * @var string
     *     NOTE: $input2 should follow the following restrictions
     *     You can have one of the following value
     *     a
     *     ab
     *     abc
     *     abcd
     *     Your length of the value should be
     *     Greater than 2
     *     Less than 3
     */
     public $input2;

I have highlighted the additional rules compared with $input, so you can see the difference.

SimpleContent Extension

Simple Content extension is extending a simple type to make a complex type. Say we have an element (say with the name “mystring”) and it has “xs:string” simple type.

<xs:element name="mystring" type="xs:string"/>

And here is a valid xml with this schema.

<mystring>this can contain only string</mystring>

So if I say I’m going to make a complex type extending this simple type you may think that I’m going to add element in to that. In fact I will create a complex type by adding an attribute.

<mystring myint="3">this can contain only string</mystring>

The schema to this xml will be something like this. (Note that I have assumed there is an schema element named “mystring” with the type “myStringType”)

            <xs:complexType name="myStringType">
                <xs:simpleContent>
                    <xs:extension base="xs:string">
                        <xs:attribute name="myint" type="xs:int"/>
                    </xs:extension>
                </xs:simpleContent>
            </xs:complexType>

The PHP generated code for this schema is something like this,

class myStringType {

    /**
     * @var int
     */
    public $myint;

    // The "value" represents the element 'myStringType' value..

    /**
     * @var string
     */
    public $value;

}

So as you can see it creates a PHP class for that schema type with member variables for each attributes and finally for the value of the parent type. So in order to represent the above mentioned xml, you will use the following PHP code.

$type = new myStringType();

$type->myint = 3;
$type->value = "this can contain only string";

Next we will look at the inheritance with complexContent Extension.

ComplexContent Extension

This is to create a complex type by inheriting another complexType.

            <!-- the parent type -->
            <xs:complexType name="parentType">
                <xs:sequence>
                    <xs:element name="demo3" type="xs:int"/>
                    <xs:element name="demo4" type="xs:string"/>
                </xs:sequence>
            </xs:complexType>

            <!-- the child type -->
            <xs:complexType name="childType">
                <xs:complexContent>
                    <xs:extension base="tns:parentType">
                        <xs:sequence>
                            <xs:element name="demo1" type="xs:int"/>
                            <xs:element name="demo2" type="xs:string"/>
                        </xs:sequence>
                    </xs:extension>
                </xs:complexContent>
            </xs:complexType>

So here the childType will inherit the ‘demo3′ and ‘demo4′ elements from the parent type. We will see how is the PHP generated code looks like.

class parentType {

    /**
     * @var int
     */
    public $demo3;

    /**
     * @var string
     */
    public $demo4;

}

class childType extends parentType {

    /**
     * @var int
     */
    public $demo1;

    /**
     * @var string
     */
    public $demo2;

}

It has uses the PHP inheritance to reprensent the schema inheritance. And the nice thing is you can use the childType for the places you have to use the parentType.  That is the theoy we learn at the inheritance class of other languages (Java, C++) too.

So say there is another complexType (say “anotherChildType”) inheriting from the type “parentType” and one another complexType (say “nextLevelChildType”) inheriting this time from “childType” (which in fact inheriting from the “parentType” as mentioned above).

So our types tree would be something like this.

--- parentType
         |
         +-------- childType
         |              |
         |              +------------- nexLevelChildType
         |
         +-------- anotherChildType

And lets say there is a schema element called ‘input3′ with the type parentType. Then the generated variable for the input3 element will be like following code segment.

    /**
     * @var (object)parentType
     *    Or one of following derived class(es)
     *       childType
     *       nextLevelChildType
     *       anotherChildType
     */
    public $input3;

This comment tells you that you can actually use the inherited types in place of the parent type according to your preferences.

September 30th, 2008XPath in SimpleXML

SimpleXML as it name imply, is a very simple API to traverse XML implemented specially in PHP language. It is very similar to the XPath, but since it has more PHP friendly syntax PHP developers really like to use it.
As an Example for this XML:

<dwml>
  <data>
    <location>
      <location-key>point1</location-key>
      	<point latitude="37.39" longitude="-122.07"></point>
      </location>
  </data>
  .....
</dwml>

XPATH Query to take the latitude in more general way

/dwml/data/location/point/@latitude

Where as with simple XML it is just a familiar PHP statement,

$simplexml->data->location->point->attributes()->latitude

Anyway still you can use the xpath inside your simplexml code. You can execute xpath queries by calling xpath function from any SimpleXMLEelment. It will return an array of SimpleXMLElement that match your query. So for the above example your XPath query would be something  like this,

$simplexml= new SimpleXMLElement($xml);
$lats =  $simplexml->xpath('/dwml/data/location/point/@latitude');
echo $lats[0];

This simplicity allows you to choose between these two methods interchangeably as best fit per your application. Here are some cases that I think use of XPath is more easy.

Ability to use of XPath shorthand
Take the above example XML it self. If there is only one attribute named ‘latitude’ throughout the XML you can call that value by

//@latitude

If XML node name or attribute name contains characters like ‘-’ which are not allowed in PHP for variable names
In the example if you want to access the value inside ‘location-key’ node using simplexml it would be like,

echo $simplexml->data->location->location-key;

This will not give you the expected result as PHP will try to think ‘location’ and ‘key’ as two taken in ‘location-key’. So this particular code can be replaced with the xpath function.

$keys =  $simplexml->xpath('/dwml/data/location/location-key');
echo $keys[0];

You want to iterate through node with a same name in an XML

If the nodes which we want to iterate is in organized positions in an XML (like the one in following) both approaches can be used with same easiness.

<root>
  <mynode>value1</mynode>
  <mynode>value2</mynode>
  <mynode>value3</mynode>
  <mynode>value4</mynode>
  <mynode>value5</mynode>
</root>

But how if the ‘mynode’ was in different locations in an XML like this,

<root>
  <anothernode>
     <mynode>value1</mynode>
  </anothernode>
  <anotheranothernode>
     <anotheranotheranothernode>
       <mynode>value2</mynode>
     </anotheranotheranothernode>
     <mynode>value3</mynode>
  </anotheranothernode>
  <mynode>value4</mynode>
</root>

You can iterate all the ‘mynode’ nodes with the following xpath query.

//mynode

Note that this case can be handled easily in DOM with the getElementsByName.

To use the power of XPath functions and Axes
You can use the XPath functions like last(), position() and even string manipulation functions like substring() in a XPath statement.
For an example in the above example, if you want only take the value of last ‘mynode’ just use this expression

//mynode[last()]

And you can use the power of axes in Xpath Queries. If you want to iterate all the ancestors from current node just use this query

'ancestor::*'

Access elements with different namespaces

<saleItems>
   <ns1:car xmlns:ns1="http:/toyota.xxx.com">$3000</ns1:car>
   <ns2:car xmlns:ns2="http:/suziki.rrr.com">$4000</ns2:car>
</saleItems>

You want to extract the cars from simpleXML. You can do this by following code.

$simplexml= new SimpleXMLElement($xml);
$ns1_childs = $simplexml->children("http:/toyota.xxx.com");
echo $ns1_childs->car;

$ns2_childs = $simplexml->children("http:/suziki.rrr.com");
echo $ns2_childs->car;

Every time you access a different namespace you have to call the children method with the namespace as an argument.

If you use XPath approach, you first register the namespces with an prefix and just use those prefix in your XPath queries.

$simplexml= new SimpleXMLElement($xml);

$simplexml->registerXPathNamespace("p1", "http:/toyota.xxx.com");
$simplexml->registerXPathNamespace("p2", "http:/suziki.rrr.com");

$toyota_cars = $simplexml->xpath('//p1:car');
$suziki_cars = $simplexml->xpath('//p2:car');

echo $toyota_cars[0];
echo $suziki_cars[0];

SimpleXML is simple and powerful in its native form. But whenever it is impossible or difficult to use you don’t need to go back for tedious DOM or manual string manipulation. You can use the xpath queries to get the work done within the simplexml environment itself.

In the code first approach, WSF/PHP will generate you the WSDL from your annotated PHP code. If you are familiar with older versions of WSF/PHP you should be already familiar with the syntax used in the annotations which are more or less the same as the conventional PHP doc comment. If you are really new to WSF/PHP annotated code here are two examples.

1. Function with simple types for input and output parameters.

/**
 * add function
 * @param int $x (maps to xsd:int)
 * @param int $y (maps to xsd:int)
 * @return int $x (maps to xsd:int)
 */
 function add($x, $y) {
   return $x + $y;
 }

2. Function with PHP classes for input and output parameters

/**
 * add function
 * @param object Vector $x (maps to objects)
 * @param object Vector $y (maps to objects)
 * @return object Vector $z (maps to objects)
 */
 function add($x, $y) {
   return $x + $y;
 }

 class Vector {
    /**
     * @var array of int $numbers (maps to xs:int)
     */
    public $numbers;
 }

WSF/PHP 2.0 has introduced new PHP annotation syntax so you have more control over the generating WSDL.

  • Now you can have custom namespaces for your schemas
  • More control over minOccurs and maxOccurs values.
  • Supporting ‘In only’ Message Exchange Pattern.
  • Generating with WS-Addressing parameters if the ‘useWSA’ option is set to true.
  • Fixes for empty input parameters.

So if you prefer Code First approach, WSF/PHP 2.0 will provide you an ideal platform for quick and easy development of web services.

Building and Traversing XML are regular tasks for any Web Service developer. We may use DOM, AXIOM or even simple String manipulation functions to do that. Normally this takes a lot of time and effort. And if we are coding in ‘C’ it become more tedious as string manipulation in ‘C’ is not that straight forward.

What ADB does is it generates a set of ‘C’ functions specially for our XML Schema to build and traverse the XML.
Say you have the following XML Schema. (You need to have it inside a WSDL to generate the code).

        <xs:schema targetNamespace="http://dimuthu.org/adb/demo/2008/sept">
            <!-- demonstrating element-->
            <xs:element name="myDemo">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="demo1" type="xs:int"/>
                        <xs:element name="demo2" type="xs:string"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        <xs:schema/>

For this particular element there will be one adb type (adb_myDemo_t), one source (adb_myDemo.c) and one header (adb_myDemo.h) are generated. Don’t ever look at the source file (unless you want to hack it) just go through the header, it will have all the function you need to manipulate your ADB.

It will have following set of functions,

To create and free the object
  • adb_myDemo_create
  • adb_myDemo_free
Getters and Setters to manipulate Data
  • adb_myDemo_get_demo1
  • adb_myDemo_set_demo1
  • adb_myDemo_get_demo2
  • adb_myDemo_set_demo2
Build and Parse XML
  • adb_myDemo_serialize
  • adb_myDemo_deserialize

First we will check how to build a simple XML using an ADB object.

    adb_myDemo_t *mydemo = adb_myDemo_create(env);
    adb_myDemo_set_demo1(mydemo, env, 3); /* some arbitrary value */
    adb_myDemo_set_demo2(mydemo, env, "some arbitrary string");
    axiom_t *xml = adb_myDemo_serialize(mydemo, env, NULL, NULL, AXIS2_TRUE, NULL, NULL);

So now we have the AXIOM representation of the XML which we just build using ADB.

<ns0:myDemo xmlns:ns0="http://dimuthu.org/adb/demo/2008/sept">
    <ns0:demo1>3</ns0:demo1>
    <ns0:demo2>some arbitrary string</ns0:demo2>
</ns0:myDemo>

Anyway ADB is easier when you want to navigate through an XML. (you can read data randomly as you preferred). Here we starting from the AXIOM representation of our XML.

      adb_myDemo_t *mydemo= adb_myDemo_create( env);
      adb_myDemo_deserialize(mydemo, env, &xml, NULL, AXIS2_FALSE))
      int demo1 = adb_myDemo_get_demo1(mydemo, env);
      printf("My Demo1 is: %d\\n", demo1);
      axis2_char_t *demo2 = adb_myDemo_get_demo2(mydemo, env);
      printf("My Demo2 is: %s\\n", demo2);

I have printed the Data contained in the XML with the help of ADB objects.

In ordre to download the Codegen tool with ADB you have to download the Axis2/Java package.

If you want to learn more about ADB, Just go through more Axis2/C Codegen / ADB resources which I have blogged few weeks ago.

In a valid XML you can only have text and you can not have binary characters. SOAP which in fact an XML is also having this issue. So it is not staright forward to send binary data in SOAP. But with WSO2 WSF/PHP 1.3.2 It is really easy to send binaries. Check the online WSF/PHP Mtom Sample sources to understand the few lines that needed to send and serve binaries.

To understand what is happening inside WSF/PHP to send your message we will first take a simple demo. To understand the messages I will be sending text data rather than binary so you can clearly see how your data goes through the wire.

Here is my code to send the binary. (in fact a test in this percular case)

<?php
$requestPayloadString = <<<XML
<ns1:upload xmlns:ns1="http://php.axis2.org/samples/mtom">
  <ns1:fileName>test.txt</ns1:fileName>
  <ns1:image xmlmime:contentType="text/txt" xmlns:xmlmime="http://www.w3.org/2004/06/xmlmime">

    <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:myid1"></xop:Include>
  </ns1:image>
</ns1:upload>
XML;

try {
    $f = file_get_contents("test.txt");

    $requestMessage = new WSMessage($requestPayloadString,
        array("to" => "http://localhost/my_mtom_service.php",
        "attachments" => array("myid1" => $f)));

    $client = new WSClient(array("useMTOM" => "FALSE"));

    $responseMessage = $client->request($requestMessage);

    echo $responseMessage->str;

} catch (Exception $e) {
    if ($e instanceof WSFault) {

        printf("Soap Fault: %s\\n", $e->Reason);
    } else {

        printf("Message = %s\\n",$e->getMessage());
    }
}

?>

And test.txt has the following text

TEXT as BINARY

In here the ‘xop:include’ element is where you going to send either the binary data or some reference to binary data.
“useMTOM” => FALSE
Note that in there in the “useMTOM” option for the WSClient I have given the value FALSE. That mean don’t use the MTOM(Message Transmission Optimization Mechanism) to serialize the message.There the generated soap message (over HTTP) will look like this,

POST /samples/mtom/mtom_upload_service.php HTTP/1.1
User-Agent: Axis2C/1.5.0
Content-Length: 404
Content-Type: application/soap+xml;charset=UTF-8
Host: 127.0.0.1:8080

<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
   <soapenv:Header/>
   <soapenv:Body>
      <ns1:upload xmlns:ns1="http://php.axis2.org/samples/mtom">
         <ns1:fileName>test.jpg</ns1:fileName>
         <ns1:image xmlmime:contentType="text/txt" xmlns:xmlmime="http://www.w3.org/2004/06/xmlmime">VEVYVCBhcyBCSU5BUlkK</ns1:image>
      </ns1:upload>
   </soapenv:Body>
</soapenv:Envelope>

The value “VEVYVCBhcyBCSU5BUlkK” is base64 encoded value for the “TEXT as BINARY” text.

<?php
echo base64_encode("TEXT as BINARY");
?>

In fact it is a standard that map each 6 bit of your binary file to an 8 bit (valid character to send through XML), so you can send the encoded value in the soap message. But no doubt you see the drawback. The encoded value is 4/3rd of the original data size. So this is not the most optimized way to send binary over SOAP.
“useMTOM” => TRUE
Setting this option TRUE will generate the following soap message over http.

POST /samples/mtom/mtom_upload_service.php HTTP/1.1
User-Agent: Axis2C/1.5.0
Transfer-Encoding: chunked
Content-Type: multipart/related; boundary=MIMEBoundary594038a6-6d95-1dd1-2b72-00197e732d4d; type="application/xop+xml"; start="<0.594038e2-6d95-1dd1-2b73-00197e732d4d@apache.org>"; start-info="application/soap+xml"; charset="UTF-8"
Host: 127.0.0.1:8080

32
--MIMEBoundary594038a6-6d95-1dd1-2b72-00197e732d4d
2

b2
content-transfer-encoding: binary
content-id: <0.594038e2-6d95-1dd1-2b73-00197e732d4d@apache.org>content-type: application/xop+xml;charset=UTF-8;type="application/soap+xml";21ff
   <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
      <soapenv:Header/>
      <soapenv:Body>
         <ns1:upload xmlns:ns1="http://php.axis2.org/samples/mtom">
            <ns1:fileName>test.jpg</ns1:fileName>
            <ns1:image xmlmime:contentType="text/txt" xmlns:xmlmime="http://www.w3.org/2004/06/xmlmime">
               <xop:Include href="cid:1.594037a2-6d95-1dd1-2b71-00197e732d4d@apache.org" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
            </ns1:image>
         </ns1:upload>
      </soapenv:Body>
   </soapenv:Envelope>32--MIMEBoundary594038a6-6d95-1dd1-2b72-00197e732d4d27econtent-transfer-encoding: binarycontent-id:
   <1.594037a2-6d95-1dd1-2b71-00197e732d4d@apache.org>content-type: text/txtfTEXT as BINARY234--MIMEBoundary594038a6-6d95-1dd1-2b72-00197e732d4d--0

Note that in the last line you see the data you send as it is. Here the binary is sent as an attachment and the element which suppose to keep the binary data refers to the attachment using the content id (check “href” attribute). It is obvious for a large binary data this is really optimized way of sending binaries.

“useMTOM” => “SWA”

WSF/PHP supports 1.3.2 supports SWA (Soap with Attachment) as well. you can enable this by setting “useMTOM” => “swa”. It is also send the binary as an attachment.  But it is not a recommended approach since you can’t secure the message when using SWA, because it can not be represented in the XML infoset. Here is the message generated enabling the “SWA”,

POST /samples/mtom/mtom_upload_service.php HTTP/1.1
User-Agent: Axis2C/1.5.0
Transfer-Encoding: chunked
Content-Type: multipart/related; boundary=MIMEBoundarybc636bdc-6d96-1dd1-31c0-00197e732d4d; type="application/xop+xml"; start="<0.bc636c40-6d96-1dd1-31c1-00197e732d4d@apache.org>"; start-info="application/soap+xml"; charset="UTF-8"
Host: 127.0.0.1:8080

32
--MIMEBoundarybc636bdc-6d96-1dd1-31c0-00197e732d4d
2

b2
content-transfer-encoding: binary
content-id: <0.bc636c40-6d96-1dd1-31c1-00197e732d4d@apache.org>content-type: application/xop+xml;charset=UTF-8;type="application/soap+xml";21b3
   <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
      <soapenv:Header/>
      <soapenv:Body>
         <ns1:upload xmlns:ns1="http://php.axis2.org/samples/mtom">
            <ns1:fileName>test.jpg</ns1:fileName>
            <ns1:image xmlmime:contentType="text/txt" xmlns:xmlmime="http://www.w3.org/2004/06/xmlmime">1.bc6368a8-6d96-1dd1-31bf-00197e732d4d@apache.org</ns1:image>
         </ns1:upload>
      </soapenv:Body>
   </soapenv:Envelope>

32
--MIMEBoundarybc636bdc-6d96-1dd1-31c0-00197e732d4d
2

7e
content-transfer-encoding: binary
content-id:
   <1.bc6368a8-6d96-1dd1-31bf-00197e732d4d@apache.org>content-type: text/txtfTEXT as BINARY234--MIMEBoundarybc636bdc-6d96-1dd1-31c0-00197e732d4d--0

In a WSDL, XML Schema is the section where it define the message format for each operations, which eventually become the real API that users are interested. And it is the most tricky part of the WSDL. Nowadays there are many tools that you can design and use WSDLs without any needs in knowing the meaning of a single line of the WSDL. But there are situations that you may find it is better you have some knowledge in XML Schema section and in WSDL overall.
For this post I m taking a simple example of use of nillable=”true” and minOccurs=”0″. Take the following example.

<xs:element name="myelements">
  <xs:complexType>
    <xs:sequence>
     <xs:element name="nonboth" type="xs:string"/>
      <xs:element minOccurs="0" name="minzero" type="xs:int"/>
      <xs:element name="nilint" nillable="true" type="xs:int"/>
      <xs:element name="nilstring" nillable="true" type="xs:string"/>
      <xs:element minOccurs="0" name="minzeronil" nillable="true" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

Just ignore the meaning of what nillable and minOccurs attributes for now. You can safely say the following XML is valid for the above Schema.

<myelements>
  <nonboth>i can't be either nil nor skipped<nonboth>
  <minzero>3<minzero>
  <nilint><nilint>
  <nilstring>i can have null, but i cant skipeed</nilstring>
  <minzeronil>i can be skipped and have the nil value<minzeronil>
</myelements>

Take the first element ‘nonboth’ in the schema, It has not any minOccurs or nillable attribute. By default minOccurs equal to 1 and nillable equal to false. That mean it can’t have nil value nor it can not be removed from the xml.

Is that making an element nil and removing the element from the XML is same? No. Take the second element in the schema ‘minzerostring’. There you have minOccurs =”0″ but there are no nillable=”true”, mean it is non-nillable. The idea is whenever you don’t want that element in your xml, you can’t have the element keeping empty like

  <minzero xsi:nil="true"><minzero>

But you can remove the whole element from the XML (since it is minOccurs=0).

The opposite of the above scenario is nillable=”true” but minOccurrs != 0. Check the ‘nilint’ element in the schema. There you can’t skip the element ‘nilint’, you have to have the element <nilint/> but it can hold a nil value.

  <nilint xsi:nil="true"></nilint>

or simply

  <nilint xsi:nil="true"/>

Note that the correct way to declare the nil element is,

  <nilint xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>

You can understand why when we look at the third element ‘nilstring’. Say you set message the following element

  <nilstring></nilstring>

You can say that this is not nil, this is an empty string. In fact an empty string is nil in some other language, But if we take XML Schema as a language, then for someone to be nil, it have to have the xsi:nil attribute set to “true” or “1″.

So going back to the ‘minzero’ which is non-nillable, by theory you should be able to write the following xml,

  <minzero/>

Since you don’t have that xsi:nil=”1″ this is not a nil value, so the condition nillable=”false” condition is preserved. But unlike for string when you set an empty element for an integer, it doesn’t sound correct. So in practice whenever some schema says non-nillable you should set some valid value.

The last one is ‘minzeronil’ element which is both nillable=”true” and minOccurs=”0″. Whenever you don’t need to set a value for this element, you have the choice of either skipping the element or setting the value of the element to nil. It is obvious rather than setting a nil value it is better you just skip the element to make the XML shorter. This is really needed specially in web services where you need the payload to be minimum as much as possible.

Say you have to prepare the XML and you don’t have valid values for any of the element. So this can be the optimum XML you can create.

<myelements xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
  <nonboth><nonboth>
  <nilint xsi:nil="1"/>
  <nilstring xsi:nil="1">
</myelements>

Read this nice article in developer works on nillable=”true” and minOccurs=”0″ for more.


© 2007 Dimuthu’s Blog | iKon Wordpress Theme by Windows Vista Administration | Powered by Wordpress