【问题标题】:灵活的递归 XML 模式
【发布时间】:2022-01-23 11:43:12
【问题描述】:

我正在尝试为此示例 XML 创建一个验证模式。我已经尝试过使用递归定义,但找不到合适的方法。请注意,IF 和 ELSE 元素可以嵌套任意次数,而 ACTIONx 元素可以以任意顺序出现。另请注意,每个元素都有自己可能不同的属性。

<?xml version="1.0" encoding="utf-8"?>
<KEYPRESS Buffer="1">
    <ACTION1 Index="15" />
    <IF Condition="0">
        <IF Condition="1">
            <ACTION1 Index="14" />
            <ELSE>
                <ACTION2 Measure="whatever" />
            </ELSE>
        </IF>
    
        <IF Condition="2">
            <IF Condition="5">
                <ACTION2 Measure="whatelse" />
                <ACTION3 Type="Flag"  />
            </IF>
            <ELSE>
                <ACTION1 Index="0" />
                <ACTION3 Type="Other" />
                <IF Condition="1">
                    <ACTION3 Type="Flag" />
                </IF>
            </ELSE>
        </IF>
    </IF>
</KEYPRESS> 

任何帮助将不胜感激。

*** 编辑 *** 非常感谢Michael Kay,很好的解决方案! 我在这里发布生成的架构,以防有人感兴趣。

<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Liquid Studio 2021 (https://www.liquid-technologies.com) -->
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="INSTRUCTION" abstract="true"/>

    <xs:element name="ACTION1" substitutionGroup="INSTRUCTION">
        <xs:complexType>
            <xs:attribute name="Index" type="xs:string" use="required" />
        </xs:complexType>
    </xs:element>
    <xs:element name="ACTION2" substitutionGroup="INSTRUCTION">
        <xs:complexType>
            <xs:attribute name="Index" type="xs:string" use="required" />
        </xs:complexType>
    </xs:element>
    <xs:element name="ACTION3" substitutionGroup="INSTRUCTION">
        <xs:complexType>
            <xs:attribute name="Type" type="xs:string" use="required" />
            <xs:attribute name="Index" type="xs:string" use="required" />
            <xs:attribute name="Value" type="xs:string" use="required" />
        </xs:complexType>
    </xs:element>
    <xs:element name="IF" substitutionGroup="INSTRUCTION">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="INSTRUCTION" minOccurs="1" maxOccurs="unbounded"/>
                <xs:element name="ELSE" minOccurs="0" maxOccurs="1"/>
            </xs:sequence>
            <xs:attribute name="Type" type="xs:string" use="required" />
            <xs:attribute name="Index" type="xs:string" use="required" />
            <xs:attribute name="Condition" type="xs:string" use="required" />
        </xs:complexType>
    </xs:element>
    <xs:element name="KEYPRESS" >
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="INSTRUCTION" minOccurs="1" maxOccurs="unbounded"/>
            </xs:sequence>
            <xs:attribute name="KeySeq" type="xs:string" use="required" />
            <xs:attribute name="Buffer" type="xs:string" use="required" />
        </xs:complexType>
    </xs:element>
    <xs:element name="ELSE" >
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="INSTRUCTION" minOccurs="1" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

</xs:schema>

【问题讨论】:

    标签: xml xsd-validation


    【解决方案1】:

    这种结构就是替换组的用途。

    定义一个抽象元素INSTRUCTION,然后将IFACTION1ACTION2ACTION3定义为INSTRUCTION的替换组的成员,每个都有自己的类型定义定义允许的属性。 KEYPRESSELSE 的内容模型似乎是 INSTRUCTION*(0 或更多指令的序列),IF 的内容模型似乎是 (INSTRUCTION*, ELSE?)(0 或更多指令的序列) (可选)ELSE)。

    ELSE 不是替换组的成员,因为它不能出现在任何出现指令的地方)。

    【讨论】:

      【解决方案2】:

      我不认为您可以定义具有可变元素名称的架构。

      element declaration 需要名称。该值的类型为xs:NCName,它只是一个字符串而不是模式。为了编写模式,您必须找出操作元素的最大数量。而且您必须为每个元素定义一个 complexType。我认为你不想这样做。

      您的 XML 文件是由不太了解 XML 的人设计的。你最好告诉他,格式必须重新设计。而不是

      <ACTION1 ...>
      

      使用

      <ACTION N="1" ...>
      

      并且架构验证将很容易。

      【讨论】:

      • 根据您的建议重新设计操作是可行的,但我仍然看不到如何声明 元素。
      • 我不同意这个 XML 的设计很糟糕(除了可能选择元素名称 ACTION1 等 - 但我想这些是占位符)。相反,这正是我期望的递归指令结构的建模方式。 XSLT 词汇表具有相似的结构(但指令名称不同),它使用递归和可扩展模式进行建模,使用替换组。
      • 我通常会建议 &lt;ACTION1&gt; 应该是 &lt;ACTION N="1"&gt;,但如果 ACTION1ACTION2 具有不同的内容模型(这将需要在 XSD 1.1 中进行条件类型分配) .当然,最好选择更具描述性的名称,例如 BEND 和 STRETCH,而不是 ACTION1 和 ACTION2。
      • ACTIONx 只是用于简化结构的占位符:它们实际上有不同的名称
      猜你喜欢
      • 2011-02-05
      • 2010-09-14
      • 1970-01-01
      • 2014-08-19
      • 1970-01-01
      • 2010-09-16
      • 2013-01-17
      • 1970-01-01
      • 2014-09-19
      相关资源
      最近更新 更多