Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSD with inline namespaces

Tags:

xml

xslt

xsd

We have a hosted application called Camstar. It provides SOAP webservices built around WCF.

I have a payload that work. I can invoke the web service from SoapUI using the payload below.

   <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <soapenv:Header>
      <WSShopFloorHeader xmlns="http://www.camstar.com/WebService/WSShopFloor">
         <UserName>abc</UserName>
         <Password>def</Password>
      </WSShopFloorHeader>
   </soapenv:Header>
   <soapenv:Body>
      <Submit xmlns="http://www.camstar.com/WebService/WSShopFloor">
         <serviceData xmlns:ns0="http://www.camstar.com/WebService/DataTypes" ns0:type="LotStart">
            <Factory>
               <__CDOTypeName/>
               <__name>X30</__name>
            </Factory>
            <Comments/>
            <Workflow>
                  <__name>TESTSTOREWF</__name>
                  <__rev/>
                  <__useROR>true</__useROR>
            </Workflow>
            <WorkflowStep>
                <__CDOTypeName/>
               <__name>DBINTSINVSPEC</__name>
            </WorkflowStep>
            <Qty>1000</Qty>
            <Qty2>10</Qty2>
            <Product>
                <__CDOTypeName/>
               <__name>9672-02-9450-D00.BW</__name>
                <__rev/>
               <__useROR>true</__useROR>
            </Product>
            <StartReason>
                  <__CDOTypeName/>
                  <__name>NORMAL</__name>
               </StartReason>
               <Owner>
                  <__CDOTypeName/>
                  <__name>PROD</__name>
               </Owner>
               <Level>
                  <__CDOTypeName/>
                  <__name>LOT</__name>
               </Level>
               <ContainerName>TEST004</ContainerName>
             </serviceData>
      </Submit>
   </soapenv:Body>
    </soapenv:Envelope>

I am unable to figure out how to create an XSD based on the above XML. The only namespaces are in the Submit and serviceData elements and they are inline.

Also how to create XSLT if I need to generate the name xml from one source to the other?

like image 248
RKS Avatar asked Feb 01 '26 09:02

RKS


1 Answers

A schema definition can only define one namespace - so you need to write a separate schema definition for each namespace you need.

Since you have two namespaces (.../WSShopFloor and .../DataTypes - the "..." is just my abbreviation). you need two schema definitions.

Let's start with the easy one: the schema definition for the .../DataTypes namespace. I've put it in a file names "types.xsd" - this is important for when we import it later. The only thing it does is define the type attribute in that target namespace:

$ cat types.xsd
<xsd:schema
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 targetNamespace="http://www.camstar.com/WebService/DataTypes"
>
  <xsd:attribute name="type"/>
</xsd:schema>

Now for the schema definition for the .../WSShopFloor namespace. (I won't do all the contents, just enough to address the namespace issues. I'll pretend that the <Factory> just has string content, and skip all the elements in it.)

<xsd:schema
 elementFormDefault="qualified"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:ns0="http://www.camstar.com/WebService/DataTypes"
 xmlns:tns="http://www.camstar.com/WebService/WSShopFloor"
 targetNamespace="http://www.camstar.com/WebService/WSShopFloor"
>
  <xsd:import
    namespace ="http://www.camstar.com/WebService/DataTypes"
    schemaLocation = "types.xsd"/>

  <xsd:import
    namespace = "http://schemas.xmlsoap.org/soap/envelope/"
    schemaLocation = "http://schemas.xmlsoap.org/soap/envelope/"/>

  <xsd:element name="WSShopFloorHeader">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="UserName" type="xsd:string"/>
        <xsd:element name="Password" type="xsd:string"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>

  <xsd:element name="Submit">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="serviceData">
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="Factory" type="xsd:string"/>   <!-- skip -->
            </xsd:sequence>
            <xsd:attribute ref="ns0:type"/>
          </xsd:complexType>
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>

</xsd:schema>

Firstly, see the import of the types.xsd schema definition, and that (at the top), ns0 refers to the same .../DataTypes namespace. Look down further, to the <serviceData> element definition, that has a attribute within it that refers to that definition in the that namespace.

Second, we also had to import the soap envelope schema definition. BTW: the schema is actually at the namespace URI, and the parser downloads it. You could also download it, and refer to the filename you gave it (actually, that's what I did - it runs faster without downloading each time).

Just for your interest, have a look at the .../soap/envelope schema - it defines top level element <Envelope>, and because we import it, our documents can have that as a top level element too. The <Envelope> defines <Header> and <Body> elements. <Header> can contain any content, provided it's in a different namespace (##other):

<xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>

<Body> can contain any content, at all (##any - that is, including those defined in this, the .../soap/envelope, schema

<xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>

The processContents="lax" means it only validates the content if it can obtain the schema - if it can't get the schema, it doesn't give an error. Therefore, to be sure that my schema was actually being used, I deliberately introduced a mistake (e.g. insert a letter in an element name), to see if an error was reported.


BTW: I wonder if there is an error in your xml - the <serviceData> element has a ns0:type attribute, from the .../Datatypes namespace. But that is the only thing used from that namesapce... I would expect if the element is marked as a "type", then all its contents from come from that namespace, which would be done with a xmlns attribute... so maybe that was omitted? [Of course, I'm just guessing here - maybe it is correct as is]

I'm just learning this too, so there might be mistakes or misunderstandings in the above - if anyone sees an error, please correct me!

like image 102
13ren Avatar answered Feb 03 '26 08:02

13ren