3

我们有一个名为 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?

4

2 回答 2

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 信封模式定义。顺便说一句:模式实际上位于命名空间 URI,解析器会下载它。你也可以下载它,并参考你给它的文件名(实际上,这就是我所做的——它运行得更快,无需每次都下载)。

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

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

<Body>可以包含任何内容,完全(##any- 也就是说,包括在 this, the .../soap/envelope, schema中定义的内容

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

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


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

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

于 2012-11-29T11:11:06.580 回答
0

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

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

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

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

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

我还尝试过尝试使用 XSD 对抗 Soap XML 的 .net 代码。这是链接 ..但恐怕..我不能成功!

如果您手动验证 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

于 2012-11-29T12:45:37.813 回答