【问题标题】:Make XML elements required based on attribute values in XSD根据 XSD 中的属性值制作所需的 XML 元素
【发布时间】:2015-06-02 20:49:40
【问题描述】:

我的要求是有一个 XSD 文件,它可以根据属性值检查元素。我能够将 XSD 编写到可以限制Application/@Type 的属性值的程度。谁能帮我完成 XSD 文件,我可以根据Application/@Type 属性在其中制作一些所需的元素?

我想做

  • PackageArg 仅当 Application/@Type 为“批处理”时才需要
  • Version 仅当 Application/@Type 为“服务”时才需要
  • Project 仅当 Application/@Type 是 Web 或“服务”时才需要

XML 文件

<Applications>        
    <Application Name="ConfigManagement" Type="Web">            
        <ProjectDirName>ConfigManagement</ProjectDirName>
        <Project>Web.ConfigManagement.csproj</Project>
        <OutputDirName>ConfigManagement</OutputDirName>            
    </Application>
    <Application Name="Util" Type="Web">            
        <ProjectDirName>Web</ProjectDirName>
        <Project>Web.csproj</Project>        
        <OutputDirName>Util</OutputDirName>    
    </Application>
    <Application Name="ConfigService" Type="Service">
        <ProjectDirName>WebServices\ConfigService</ProjectDirName>
        <Project>ConfigService.csproj</Project>    
        <Version>2015\04</Version>
        <OutputDirName>ConfigService</OutputDirName>
    </Application>
    <Application Name="DeliverEmail" Type="Batch">        
        <ProjectDirName>\Batch\DeliverEmail</ProjectDirName>
        <PackageArg>Release</PackageArg>        
        <OutputDirName>Tidal\DeliverEmail</OutputDirName>            
    </Application>
</Applications>

XSD 文件

<xs:element name="Applications" maxOccurs="1">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="Application" maxOccurs="unbounded" minOccurs="1">
        <xs:complexType>
          <xs:all>
            <xs:element type="xs:string" name="ProjectDirName"/>
            <xs:element type="xs:string" name="Project" minOccurs="0"/>
            <xs:element type="xs:string" name="Version" minOccurs="0"/>
            <xs:element type="xs:string" name="PackageArg" minOccurs="0"/>
            <xs:element type="xs:string" name="OutputDirName"/>
          </xs:all>
          <xs:attribute type="xs:string" name="Name" use="optional"/>
          <xs:attribute name="Type" use="required">
            <xs:simpleType>
              <xs:restriction base="xs:string">
                <xs:enumeration value="Web"/>
                <xs:enumeration value="Batch"/>
                <xs:enumeration value="Service"/>
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
</xs:element>

【问题讨论】:

  • 请将您的链接材料直接添加到您的问题中。如果您提供了一个示例,说明您希望被视为有效的内容以及您希望被排除为无效的内容,这也会很有帮助。此外,请不要使用不是特定于您的问题的标签 - 这不是专门针对 C# 的问题。
  • @DanField 是对的——你的问题应该是独立的。这次我已经为您解决了这个问题,但请在以后的问题中包含所有需要的材料。谢谢。
  • 感谢您的编辑和建议。下次我发布问题时,我会关注他们。

标签: xml xsd msxml


【解决方案1】:

更新: OP 已编辑问题以删除xs:assert 的使用,并在 cmets 中声明必须在 C# 中进行验证。 OP 问题的答案现在变成:

您不能强制使用 XSD 1.0 根据属性值改变元素的需求性的约束,并且 Microsoft 不支持 XSD 1.1,因此您必须放宽约束或在外部检查它们你的 XSD。


原始 XSD 1.1 答案

(为未来读者的利益保留)

你很接近,但你的断言,

      <xs:assert test="count(./PackageArg[@type eq 'Batch']) eq 1"/>

在PackageArg 上测试@type,而它应该在Application 上测试@Type。

以下 XSD 将验证您的 XML 并强制执行与属性相关的要求:

XSD 1.1

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
           vc:minVersion="1.1">
  <xs:element name="Applications">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Application" maxOccurs="unbounded" minOccurs="1">
          <xs:complexType>
            <xs:all>
              <xs:element type="xs:string" name="ProjectDirName"/>
              <xs:element type="xs:string" name="Project" minOccurs="0"/>
              <xs:element type="xs:string" name="Version" minOccurs="0"/>
              <xs:element type="xs:string" name="PackageArg" minOccurs="0"/>
              <xs:element type="xs:string" name="OutputDirName"/>
            </xs:all>
            <xs:attribute type="xs:string" name="Name" use="optional"/>
            <xs:attribute name="Type" use="required">
              <xs:simpleType>
                <xs:restriction base="xs:string">
                  <xs:enumeration value="Web"/>
                  <xs:enumeration value="Batch"/>
                  <xs:enumeration value="Service"/>
                </xs:restriction>
              </xs:simpleType>
            </xs:attribute>
            <xs:assert test="PackageArg or @Type != 'Batch'"/>
            <xs:assert test="Version or @Type != 'Service'"/>
            <xs:assert test="Project or not(@Type = 'Web' or @Type = 'Service')"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

请注意,Microsoft 不支持 XSD 1.1。 (您已使用“msxml”标记您的问题)。

【讨论】:

  • 很抱歉造成混淆。我在尝试不同的东西,但我输入了错误的行。
  • 行错了?你的意思是错误的“标签”(msxml)吗?更重要的是,这个答案对你有帮助吗?
  • 我并不是要包含 Assert 标签。我想在 C# 中使用 xsd 文件,所以我不能使用 XSD1.1。
  • 好吧,在您的 XSD 中有 xs:assert 意味着您可以使用 XSD 1.1。 您无法在 XSD 1.0 中强制执行您的要求;您需要 XSD 1.1,否则您必须在 XSD 之外强制执行基于属性的元素要求约束。
  • 对不起,我编辑了我的问题。谢谢你的建议
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多