【问题标题】:XML validation (different child tags) based on attribute value基于属性值的 XML 验证(不同的子标签)
【发布时间】:2014-05-09 20:06:24
【问题描述】:

我正在编写一个仪表板设计器,它将基于 xml 值创建小部件。

喜欢

<dashboard>
    <widget type="chart">

    </widget>
</dashboard> 

我想根据 @type 的值更改 内的标签,例如如果 type="chart"那么它应该允许不同的标签

<dashboard>
    <widget type="chart">
        <title text="Chart Title"></title>
        <plotOptions>
            <plotOptions>
                <pie showInLegend="true" shadow="false" innerSize="50%">
                    <dataLabels color="#fff" distance="-20" format="{point.percentage:.0f} %" overflow="false"></dataLabels>
                </pie>
            </plotOptions>
            <legend width="150" align="right" x="10" layout="vertical">
                <navigation></navigation>
            </legend>
            <tooltip enabled="false"></tooltip>
            <exporting enabled="true"></exporting>
        </plotOptions>
    </widget>
</dashboard>

如果我们有 type="table" 它应该允许不同的标签

<dashboard>
    <widget type="table">
        <title text="Table Title"></title>
        <thead>
            <tr>
                <th>One</th>
                <th>Two</th>
                <th>Three</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>DS.One</td>
                <td>DS.Two</td>
                <td>DS.Three</td>
            </tr>
        </tbody>
    </widget>
</dashboard> 

它还应该在 XML 编辑器中给出自动建议,例如 "ECLIPSE"

【问题讨论】:

    标签: xml xml-parsing xsd xsd-validation xsd-1.1


    【解决方案1】:

    其他解决方案是使用 XML Schema 1.1 中的类型替代。 使用替代类型,您可以根据属性的值为元素设置不同的类型。在您的情况下,如果@type 的值为“chart”,则可以为小部件元素设置“chart”类型,如果@type 的值为“table”,则可以设置“table”类型。 请参阅下面的示例架构:


    <xs:element name="dashboard">
        <xs:complexType>
            <xs:sequence maxOccurs="unbounded">
                <xs:element name="widget" type="widgetBaseType">
                    <xs:alternative test="@type='chart'" type="chart"/>
                    <xs:alternative test="@type='table'" type="table"/>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    
    <xs:complexType name="widgetBaseType">
        <xs:attribute name="type"/>
    </xs:complexType>
    
    <xs:complexType name="chart">
        <xs:complexContent>
            <xs:extension base="widgetBaseType">
                <xs:sequence>
                    <xs:element name="title"/>
                    <xs:element name="plotOptions"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    
    <xs:complexType name="table">
        <xs:complexContent>
            <xs:extension base="widgetBaseType">
                <xs:sequence>
                    <xs:element name="title"/>
                    <xs:element name="thead"/>
                    <xs:element name="tbody"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    

    【讨论】:

    • 这确实是一个更简单的解决方案。不需要命名空间或复杂的断言。
    【解决方案2】:

    如果您在源代码中限定它们,则一种解决方案是根据其名称空间验证内容:

    <dashboard>
        <widget type="chart">
            <title text="Chart Title"></title>
            <plotOptions xmlns="http://jaspersoft.com/highcharts"> ... </plotOptions>
        </widget>
    </dashboard>
    

    如果您可以将 HTML 表格元素包装在 &lt;table&gt; 中,则编写断言会更简单:

    <dashboard>
        <widget type="table">
            <title text="Table Title"></title>
            <table xmlns="http://www.w3.org/1999/xhtml">
                <thead>...</thead>
                <tbody>...</tbody>
            </table>
        </widget>
    </dashboard> 
    

    使用xs:choice,您可以选择由命名空间限定的不同xs:any 元素之一。在&lt;assert&gt; 中,您可以将内容的命名空间和标记名与type 属性的内容进行比较:

    <xs:element name="widget">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="title">...</xs:element>
    
                <xs:choice>
                    <xs:any namespace="http://www.w3.org/1999/xhtml" processContents="lax" maxOccurs="unbounded" minOccurs="0"/>
                    <xs:any namespace="http://jaspersoft.com/highcharts" processContents="lax" maxOccurs="unbounded" minOccurs="0"/>
                </xs:choice>
    
            </xs:sequence>
            <xs:attribute name="type" type="xs:string"/>
    
            <xs:assert test="(@type = 'table' and *[local-name() = 'table'       
                                                    and namespace-uri() = 'http://www.w3.org/1999/xhtml'])
                         or  (@type = 'chart' and *[local-name() = 'plotOptions' 
                                                    and namespace-uri() = 'http://jaspersoft.com/highcharts'])"/>
    
        </xs:complexType>
    </xs:element>
    

    【讨论】:

      猜你喜欢
      • 2016-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-18
      • 1970-01-01
      • 2020-07-17
      • 1970-01-01
      • 2019-09-14
      相关资源
      最近更新 更多