【问题标题】:XSD with inline namespaces具有内联命名空间的 XSD
【发布时间】:2012-11-28 16:33:03
【问题描述】:

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

【问题讨论】:

  • 你有两个问题!这两个问题的答案完全不同,彼此无关!
  • @InfantProgrammer'Aravind' 你能对某人的第一个问题友好一点吗?只关注问题——无需夸大和感叹。我发现 SO (大部分)是一个友好和乐于助人的社区,我想保留和鼓励这一点。如果你知道 XSD 问题的答案,我有兴趣学习。
  • @user1860519 请为您的 XSLT 问题创建一个新问题,并澄清您的问题(例如,我认为“名称”可能是一个错字)。所以(以及许多其他事情!)一次做一件事效果最好。
  • @13ren,当然......我很遗憾我有点粗鲁,这不是我的本性!同时我实际上正在为这两个问题准备答案.. XSLT 我被困在决定是写基础知识还是指导他学习 XSLT 教程。..
  • @13ren 你是对的,浏览器没有刷新。非常感谢您的详细解释。我想知道如何使用 2 个命名空间。你的解释很有道理。我会试一试。我将开始一个关于 WSDL 的新问题。可能我会在发布之前搜索 SO。

标签: xml xslt xsd


【解决方案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 命名空间的架构定义。 (我不会做所有的内容,只是解决命名空间问题。我会假装&lt;Factory&gt; 只是有字符串内容,并跳过其中的所有元素。)

<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 命名空间。再往下看,&lt;serviceData&gt; 元素定义,其中有一个属性,该属性引用该命名空间中的该定义。

其次,我们还必须导入soap 信封模式定义。顺便说一句:模式实际上位于命名空间 URI,解析器会下载它。您也可以下载它,并参考您给它的文件名(实际上,这就是我所做的 - 它运行速度更快,无需每次都下载)。

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

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

&lt;Body&gt; 可以包含任何内容(##any - 即包括在此定义的内容,.../soap/envelope,架构

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

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


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

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

【讨论】:

  • 这真的很有帮助。非常感谢。
【解决方案2】:

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

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

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

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

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

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

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

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

首先,您尝试照原样复制整个 XML .. 了解 &lt;copy&gt; and &lt;apply-templates select="@*|*|text()"/&gt;pairs .. 了解身份模板!! @ 通知属性,* 通知元素,文本数据为 text() 必须被理解..

尝试添加和删除元素和属性.. 使用&lt;template match="element_or_Attribute_name"/&gt; 删除元素/属性.. 也&lt;value-of select=""/&gt;在这里出现..

尝试将属性转换为元素,反之亦然..

尝试将一组元素或父标记 .. 移动到其他一些 .. 使用并理解&lt;for-each select=""/&gt; 的意义(它会 在这里有必要..)..还编写代码来重命名标签.. 和属性..

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

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

【讨论】:

  • 是的,我还发现在线验证工具只能接受一个模式......我想也许,如果你在其他地方托管其他模式,并在 import/@schemaLocation 中使用该 URL 可能 工作 - 但这真的很尴尬。 :) Re .Net: 我不使用.Net,但我认为必须有一种方法可以指定多个模式......啊! XmlValidatingReader 有一个Schemas property,用于模式集合。 (注意:它也说它是“过时的”......)
  • @13ren,我记得正确指定了import/@schemaLocation!好。我还尝试使用 XSD 生成器在线为 Soap XML 生成 Schema 文件。当然它们会生成,但它们不起作用!
  • @13ren,是的,.Net 不支持太多.. :(
  • 顺便说一句:我使用 xmllint 进行模式检查,它几乎适用于所有事情。 xmlsoft.org/downloads.html(如果你需要的话,有一个 windows 端口)。
猜你喜欢
  • 2015-04-28
  • 2010-12-23
  • 1970-01-01
  • 2015-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-19
相关资源
最近更新 更多