带有内联命名空间的XSD

时间:2012-11-28 16:33:03

标签: xml xslt xsd

我们有一个名为Camstar的托管应用程序。它提供了围绕WCF构建的SOAP Web服务。

我有一个有效载荷。我可以使用下面的有效负载从SoapUI调用Web服务。

   <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>

我无法弄清楚如何基于上述XML创建XSD。唯一的命名空间位于Submit和serviceData元素中,它们是内联的。

如果我需要从一个源到另一个源生成名称xml,如何创建XSLT?

2 个答案:

答案 0 :(得分:1)

模式定义只能定义一个名称空间 - 因此您需要为所需的每个名称空间编写单独的模式定义。

由于您有两个名称空间(.../WSShopFloor.../DataTypes - “...”只是我的缩写)。你需要两个模式定义。

让我们从简单的开始:.../DataTypes命名空间的模式定义。我把它放在文件名“types.xsd”中 - 这对我们稍后import时很重要。它只做 的事情是在目标命名空间中定义type属性:

$ 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>

现在为.../WSShopFloor命名空间的模式定义。 (我不会做所有的内容,只是足以解决名称空间问题。我会假装<Factory>只有字符串内容,并跳过其中的所有元素。)

<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>

首先,请参阅导入types.xsd架构定义,并且(在顶部),ns0引用相同的.../DataTypes命名空间。进一步向下查看<serviceData>元素定义,其中包含一个引用该命名空间中该定义的属性。

其次,我们还必须导入soap信封架构定义。 BTW:模式实际上位于命名空间URI,解析器下载它。你也可以下载它,并参考你给它的文件名(实际上,这就是我所做的 - 它运行得更快,而不是每次下载)。

为了您的兴趣,请查看.../soap/envelope架构 - 它定义顶级元素<Envelope>,因为我们导入它,我们的文档也可以将其作为顶级元素。 <Envelope>定义了<Header><Body>个元素。 <Header>可以包含任何内容,只要它位于不同的命名空间(##other)中:

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

<Body>可以包含任何内容(##any - 也就是说,包括在此定义的内容,.../soap/envelope,架构

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

processContents="lax"表示只有在可以获取模式的情况下才会验证内容 - 如果它无法获取模式,则不会产生错误。因此,为了确保我的架构实际被使用,我故意引入了一个错误(例如在元素名称中插入一个字母),以查看是否报告了错误。


BTW:我想知道你的xml中是否有错误 - <serviceData>元素来自ns0:type命名空间的.../Datatypes属性。但是这是从名称中使用的唯一东西......我希望如果元素被标记为“类型”,那么它的所有内容都来自该命名空间,这将使用xmlns属性来完成。 ..也许这被省略了? [当然,我只是在这里猜测 - 也许这是正确的]

我也只是学习这个,所以上面可能有错误或误解 - 如果有人看到错误,请纠正我!

答案 1 :(得分:0)

我将分两部分回答这个问题:

1)SoSD XML的XSD: 好。分享我的个人经验..我们从第三方获得SOAP XML! SOAP XML实际上称为WSDL,具有一堆命名空间,在我们的实时业务中,这些命名空间发生了变化..

另一方面,如果您将其视为XML:
当您遇到具有不同节点的不同命名空间的XML文件时!我的意思是,为父节点提供的命名空间与子节点的命名空间不同。你需要创建多个与<import>链接的XSD文件 13ren 已经发布了答案..但!!这种验证不适用于大多数XML解析器!我自己经历过!

我观察到它在MS-visual studio中工作,其中多个XSD分配工作!当你尝试在.Net中使用XmlValidatingReader加载XML和XSD时,这就失败了!与任何其他在线验证工具相同的行为..

这个SOAP XML还有一个问题。它们带有一堆不同的Namespace,通过这种方法我们不能继续添加与Namespace数量一样多的XSD文件!!

我还尝试过尝试对Soap XML使用XSD的.net代码。 here is the link ..但我很害怕..我不能成功!

如果您手动验证XML,我会赞同13ren的方法!

2)XML的XSLT: XSLT是一种函数式编程语言(不是程序性的)。这就是你练习XSLT的方法:

  

首先,您尝试复制整个XML。了解其重要性   <copy> and <apply-templates select="@*|*|text()"/>对..了解身份模板!!   @和元素通过*和文本数据通知   必须理解text()..

     

尝试添加和删除元素和属性..使用<template match="element_or_Attribute_name"/>删除元素/属性。   同样<value-of select=""/>在这里进行了描述..

     

尝试将属性转换为元素和反之亦然。

     

尝试在其他一些元素下移动一组元素或父标记..   使用并理解<for-each select=""/>的重要性(它会   这里有必要..)..也写代码重命名标签..   和属性..

     

使用不同的子标记名称和孙标记构建一个巨大的XML   构建一个可以添加和删除大量标签的XSL。使用所有这些可能性   您在此之前尝试过(一次一个)

供您参考的教程: https://stackoverflow.com/questions/1858345/xsltwhich-is-the-best-tutorial-you-would-like-to-recommend

相关问题