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