XML validation (different child tags) based on attribute value

一世执手 提交于 2019-11-28 02:08:04

问题


I am writing an dashboard designer that will create widgets based on xml values.

like

<dashboard>
    <widget type="chart">

    </widget>
</dashboard> 

I want to change the tags inside the <widget> based on the value of @type for example if type="chart" Then it should allow different tags

<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>

AND if we have type="table" It should allow different tags

<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> 

And it should also give auto suggest in XML editor like "ECLIPSE"


回答1:


Other solution is to use type alternative, from XML Schema 1.1. Using the alternative types you can set different types to an element depending on the value of an attribute. In your case you can set to the widget element the "chart" type if the value of the @type is "chart", and the "table" type in case the value of the @type is "table". See below a sample schema:


<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:


One solution would be to validate the contents according to their namespaces, if you qualify them in your source:

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

If you can wrap the HTML table elements inside a <table> it will be simpler to write the assertions:

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

With an xs:choice you can select one of different xs:any elements qualified by a namespace. In the <assert> you can compare the content's namespace and tag-name with the contents of the type attribute:

<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>


来源:https://stackoverflow.com/questions/23545674/xml-validation-different-child-tags-based-on-attribute-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!