XML Schema - Rekursion

Hi,

ich muss in XML ein Regelwerk bestehende aus Bedingungen (Conditions) und auszulösenden Aktionen (Actions) abbilden. Dabei bestehe eine Regel (Rule) immer aus genau 1 Condition und 1 Action. Natürlich sollen auch komplexe Bedingungen möglichsein, was zu kombinierten Bedingungen (CombinedCondition) führt.

Das Problem liegt gerade darin, diese CombinedConditions in XSD abzubilden:

Code:
<xs:element name="automation" minOccurs="1" maxOccurs="1" >
<xs:complexType>
<xs:sequence>

	<xs:element name="rule" minOccurs="0" maxOccurs="unbounded" >
	<xs:complexType>
	<xs:sequence>
	<xs:choice minOccurs="1" maxOccurs="1" >
	
			<xs:element name="contact" minOccurs="0" maxOccurs="unbounded">
			<xs:complexType>
				<xs:sequence />
				<xs:attribute name="name" type="xs:string" use="required" />
				<xs:attribute name="device" type="xs:string" use="required" />
				<xs:attribute name="state" type="xs:string" use="required" />
			</xs:complexType>
			</xs:element>		
			
			<xs:element name="time" minOccurs="0" maxOccurs="unbounded">
			<xs:complexType>
				<xs:sequence />
				<xs:attribute name="name" type="xs:string" use="required" />
				<xs:attribute name="hour" type="xs:integer" use="required" />
				<xs:attribute name="minute" type="xs:integer" use="required" />
				<xs:attribute name="mode" use="required" >
					<xs:simpleType>
		    		        <xs:restriction base="xs:string">
		      				<xs:pattern value="BEFORE|AFTER"/>
		    		        </xs:restriction>						
					</xs:simpleType>
				</xs:attribute>	
			</xs:complexType>
			</xs:element>	
					
			<!-- TODO: many more condition types go here -->
					
	</xs:choice>
	<xs:choice minOccurs="1" maxOccurs="1" >

			<xs:element name="switch" minOccurs="0" maxOccurs="unbounded">
			<xs:complexType>
				<xs:sequence />
				<xs:attribute name="name" type="xs:string" use="required" />
				<xs:attribute name="device" type="xs:string" use="required" />
				<xs:attribute name="state" type="xs:boolean" use="required" />
			</xs:complexType>
			</xs:element>	
			
			<!-- TODO: many more actions types go here -->
			
	</xs:choice>
	
	</xs:sequence>
	<xs:attribute name="name" type="xs:string" use="required" />
	</xs:complexType>
	</xs:element>

</xs:sequence>
</xs:complexType>
</xs:element>

Wenn ich hier jetzt eine CombinedCondition definieren würde, müssten alle anderen Definitionen von Bedinungen ja wieder als Sub-Elemente definiert werden und eben auch wieder CombinedConditions. Problem wird klar? :D Das XSD File würde unendlich lang werden :D Wie kann ich das elegant erledigen?


Grüße
serow
 
Wenn ich dich richtig verstehe, würde ein XML bei dir beispielhaft so aussehen:
Code:
<rule>
   <condition x />
   <action x />
</rule>

Wo ist das Problem statt einer Condition einfach eine Liste von Conditions zu machen, damit du sowohl einfache, als auch mehrere Conditions pro Rule haben kannst?
Also sowas:
Code:
<rule>
   <conditions>
      <condition x />
      <condition y />
   </conditions>
   <action x />
</rule>
 
Hi,

naja ist nicht ganz richtig. Das hier wären mögliche Beispiele:

Code:
<rule>
  <time-condition hour="23" minute="0" mode="AFTER" />
  <switch device="IEQ0000477:1" state="on" />
</rule>

<rule>
  <combined-condition conjunction="AND">
    <switch device="IEQ0000477:1" state="on" />
    <combined-condition conjunction="AND">
      <time-condition hour="23" minute="0" mode="AFTER" />
      <time-condition hour="6" minute="0" mode="BEFORE" />
    </combined-condition>
  </combined-condition>
  <combined-action delay="0">
    <switch device="IEQ0000477:1" state="on" />
    <alarm device="XYZ" state="on" duration="360" />
  </combined-action>
</rule>

Sowohl <time-condition /> als auch <combined-condition> sind Bedingungen. Es darf pro Rule nur eine Bedingung vorkommen. Verschachtelt dürfen sie aber sein. Gleiches gilt für Actions.

ciao
serow
 
Hm, dann wäre wohl ein ComplexType für die Condition angesagt, der entweder eine Liste aus Conditions ist, oder eine einzige Condition. Was ähnliches hab ich auf Arbeit schonmal gemacht. Muss ich morgen mal raussuchen und etwas abändern, damit es passt. Mein Problem war abstrakt ausgedrückt eine Liste von Feldern und Tabellen, die Felder enthalten, zu definieren. Das müsste eigentlich annähernd auf dein Problem passen.

/Edith:

Wenn ich es richtig verstanden hab, willst du ab dort, wo du eine komplexe Condition hast nur noch einfache Conditions drunter haben.

Das ganze natürlich equivalent bei den Actions.
 
Hi,

zusammengesetzte Conditions dürfen auch wieder solche enthalten. Irgendwo muss es dann natürlich mit einfachen Conditions aufhören. Bin sehr gespannt auf deinen Code! XML/XSD finde ich ziemlich abturnend, muss aber leider sein :D Hoffentlich ist dein Beispiel-Code irgendwie anpassbar auf mein Problem :D

Grüße
Serow
 
Mir ist nicht ganz klar ob "switch" eine Action ist und wenn ja, was diese dann im condition block macht.

An für sich sollte sowas doch gehen, oder übersehe ich da etwas ?
Code:
	<xs:element name="combined-condition">
		<xs:complexType>
			<xs:choice minOccurs="2" maxOccurs="2">
				<xs:element ref="switch" />
				<xs:element ref="time-condition" />
				<xs:element ref="combined-condition" />
			</xs:choice>
			<xs:attribute name="conjunction" type="xs:string" />
		</xs:complexType>
	</xs:element>

Falls in die "combined-condition" elemente jeweils eine Action und eine Bedingung enthalten soll einfach ne sequence die dann halt jewile einen choise block für die Action und die Bedingung enthält.
Das ganze muss dann im Prinzip ja nur noch einmal kopiert werden und in rule umbenannt werden. (Nicht schön, sollte aber funzen)
 
Hi,

danke erstmal für den Beispiel-Code! Dieses ref-Attribute kannte ich noch nicht. Habs gleich mal versucht:

Code:
<xs:element name="automation" minOccurs="1" maxOccurs="1" >
<xs:complexType>
<xs:sequence>

	<xs:element name="rule" minOccurs="0" maxOccurs="unbounded" >
	<xs:complexType>
	<xs:sequence>
	<xs:choice minOccurs="1" maxOccurs="1" >
	
			<xs:element name="contact-condition">
			<xs:complexType>
				<xs:sequence />
				<xs:attribute name="name" type="xs:string" use="required" />
				<xs:attribute name="device" type="xs:string" use="required" />
				<xs:attribute name="state" type="xs:string" use="required" />
			</xs:complexType>
			</xs:element>		
			
			<xs:element name="time-condition">
			<xs:complexType>
				<xs:sequence />
				<xs:attribute name="name" type="xs:string" use="required" />
				<xs:attribute name="hour" type="xs:integer" use="required" />
				<xs:attribute name="minute" type="xs:integer" use="required" />
				<xs:attribute name="mode" use="required" >
					<xs:simpleType>
		    		<xs:restriction base="xs:string">
		      			<xs:pattern value="BEFORE|AFTER"/>
		    		</xs:restriction>						
					</xs:simpleType>
				</xs:attribute>	
			</xs:complexType>
			</xs:element>	
					
			<!-- TODO: many more condition types go here -->
					
			<xs:element name="combined-condition">
				<xs:complexType>
					<xs:choice minOccurs="2" maxOccurs="unbounded">
						<xs:element ref="contact-condition" />
						<xs:element ref="time-condition" />
						<xs:element ref="combined-condition" />
					</xs:choice>
					<xs:attribute name="conjunction" type="xs:string" />
				</xs:complexType>
			</xs:element>
					
	</xs:choice>
	<xs:choice minOccurs="1" maxOccurs="1" >

			<xs:element name="switch-action">
			<xs:complexType>
				<xs:sequence />
				<xs:attribute name="name" type="xs:string" use="required" />
				<xs:attribute name="device" type="xs:string" use="required" />
				<xs:attribute name="state" type="xs:boolean" use="required" />
			</xs:complexType>
			</xs:element>	
			
			<!-- TODO: many more actions types go here -->

			<xs:element name="batch-action">
				<xs:complexType>
					<xs:choice minOccurs="2" maxOccurs="unbounded">
						<xs:element ref="switch-action" />
						<xs:element ref="batch-action" />
					</xs:choice>
				</xs:complexType>
			</xs:element>
			
	</xs:choice>
	
	</xs:sequence>
	<xs:attribute name="name" type="xs:string" use="required" />
	</xs:complexType>
	</xs:element>

</xs:sequence>
</xs:complexType>
</xs:element>

Ich hab auch die Namen etwas geändert, damit es eindeutiger wird und Missverständnissen vorgebeugt wird ;)

Leider bekomme ich momentan folgende Exception:

Code:
org.dom4j.DocumentException: Error on line 161 of document  : src-resolve: Cannot resolve the name 'contact-condition' to a(n) 'element declaration' component. Nested exception: src-resolve: Cannot resolve the name 'contact-condition' to a(n) 'element declaration' component.
	at org.dom4j.io.SAXReader.read(SAXReader.java:482)
	at org.dom4j.io.SAXReader.read(SAXReader.java:343)
        ...

Zeile 161 ist diese hier:

Code:
<xs:element ref="combined-condition" />

Er scheint also combined-condition nicht als Element zu kennen. :confused:


Grüße
serow
 
Du musst nicht alles hintereinander weg definieren. Ich definiere die Typen meist extra und nutze sie dann später nur noch als Typ. Dann kannst du sowas machen:
Code:
<element type="meinComplexType"/>
Damit hast du dein Problem der Rekursion quasi erschlagen. Und die refs brauchts dann auch nicht.

Ich bastel dir das morgen mal um, aber ohne das Beispiel von der Arbeit dauert mir das jetzt zu lang. Hoffe ich finde die Zeit dafür. Wenn nicht wird es erst Samstag was.
 
Stimm, das geht natürlich auch (Ist bei mir schon ein wenig her das ich das letzte mal eins schrieb).

Ich habe da mal was zusammengeschustert was zumindest erst einmal funktionieren müsste.
Ich bin dennoch gespannt auf lookshes version. :)

Code:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/ConditionStuff" xmlns="http://www.example.org/ConditionStuff" elementFormDefault="qualified">
	
	
	<xs:complexType name="combined-condition_type">
		<xs:choice minOccurs="2" maxOccurs="2">
			<xs:element name="combined-condition" type="combined-condition_type" />	
			<!-- Hier alle Conditions einfuegen  -->					
			<xs:element name="time-condition" type="time-condition_type" />
		</xs:choice>		
		<xs:attribute name="conjunction" type="xs:string" />
	</xs:complexType>
	<xs:complexType name="combined-action_type">
		<xs:choice minOccurs="2" maxOccurs="2">
			<xs:element name="combined-action" type="combined-action_type" />	
			<!-- Hier alle Actions einfuegen  -->					
			<xs:element name="switch" type="switch_type" />
			<xs:element name="alarm" type="alarm_type" />
		</xs:choice>		
		<xs:attribute name="conjunction" type="xs:string" />
	</xs:complexType>
	
	<!-- Hier die Typen definieren oder gleich in dem combined-*_type -->
	<xs:complexType name="time-condition_type">
		<xs:attribute name="hour" type="xs:int" />
		<xs:attribute name="minute" type="xs:int" />
		<xs:attribute name="mode" type="xs:string" />
	</xs:complexType>
	<xs:complexType name="switch_type">
		<xs:attribute name="device" type="xs:string" />
		<xs:attribute name="state" type="xs:string" />
	</xs:complexType>
	<xs:complexType name="alarm_type">
		<xs:attribute name="device" type="xs:string" />
		<xs:attribute name="state" type="xs:string" />
		<xs:attribute name="duration" type="xs:int" />
	</xs:complexType>
	
	<xs:element name="rule">
		<xs:complexType>
			<xs:sequence>
				<xs:choice>
					<xs:element name="combined-condition" type="combined-condition_type" />
					<!-- Hier muessen leider noch einmal alle moeglichkeiten eingetragen werden -->
					<!-- Irgendiwe kann man das hier sicherlich auch noch umgehen ;) -->
					<xs:element name="time-condition" type="time-condition_type" />
				</xs:choice>
				
				<xs:choice> 
					<xs:element name="combined-action" type="combined-action_type" />
					<!-- Hier muessen leider noch einmal alle moeglichkeiten eingetragen werden -->
					<!-- Irgendiwe kann man das hier sicherlich auch noch umgehen ;) -->
					<xs:element name="switch" type="switch_type" />
					<xs:element name="alarm" type="alarm_type" />
				</xs:choice>
			</xs:sequence>
		</xs:complexType>
	</xs:element>
	

	<xs:element name="rules">
		<xs:complexType>
			<xs:sequence maxOccurs="unbounded">
				<xs:element ref="rule" />
			</xs:sequence>
		</xs:complexType>
	</xs:element>
	
</xs:schema>

Code:
<?xml version="1.0" encoding="UTF-8"?>
<rules xmlns="http://www.example.org/ConditionStuff" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/ConditionStuff ConditionStuff.xsd ">
	<rule>
	  <time-condition hour="23" minute="0" mode="AFTER" />
	  <switch device="IEQ0000477:1" state="on" />
	</rule>
	
	<rule>
	  <combined-condition conjunction="AND">
	  	<time-condition hour="23" minute="0" mode="AFTER" />
	    <combined-condition conjunction="AND">
	      <time-condition hour="23" minute="0" mode="AFTER" />
	      <time-condition hour="6" minute="0" mode="BEFORE" />
	    </combined-condition>
	  </combined-condition>
	  
	  <combined-action>
	    <switch device="IEQ0000477:1" state="on" />
	    <alarm device="XYZ" state="on" duration="360" />
	  </combined-action>
	</rule>
</rules>
 
Zurück
Oben