changeset 23:f9846f896df3

Re #32 - Migrate WarFoundry files to using Schemas * Add missing spaces to Cats and Core XSD * Fix some incorrect namespaces in Race XSD * Copy schemas to output dir on build * Make WarFoundryXmlFactory validate against Schemas * Make WarFoundryLoader handle failed file loads slightly differently so that we can log out as a warning * Correctly structure "simpleContent" sections of Race XSD Still to do: * Work out why Race XSD doesn't like core:nonNegativeDecimal but appears to be fine with core:percentage * Migrate test files to define namespaces and make sure they match the structure
author IBBoard <dev@ibboard.co.uk>
date Thu, 12 Mar 2009 21:35:17 +0000
parents 28e99aa0053f
children 72312a7ac08a
files IBBoard.WarFoundry.API.csproj api/Factories/Xml/WarFoundryXmlFactory.cs api/WarFoundryLoader.cs dtds/race.xsd dtds/warfoundry-cats.xsd dtds/warfoundry-core.xsd
diffstat 6 files changed, 97 insertions(+), 31 deletions(-) [+]
line diff
     1.1 --- a/IBBoard.WarFoundry.API.csproj	Mon Mar 09 20:45:45 2009 +0000
     1.2 +++ b/IBBoard.WarFoundry.API.csproj	Thu Mar 12 21:35:17 2009 +0000
     1.3 @@ -1,4 +1,4 @@
     1.4 -<?xml version="1.0" encoding="utf-8"?>
     1.5 +<?xml version="1.0" encoding="utf-8"?>
     1.6  <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
     1.7    <PropertyGroup>
     1.8      <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     1.9 @@ -44,6 +44,18 @@
    1.10      <None Include="dtds\army.dtd" />
    1.11      <None Include="dtds\race.dtd" />
    1.12      <None Include="dtds\system.dtd" />
    1.13 +    <None Include="dtds\system.xsd">
    1.14 +      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    1.15 +    </None>
    1.16 +    <None Include="dtds\race.xsd">
    1.17 +      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    1.18 +    </None>
    1.19 +    <None Include="dtds\warfoundry-core.xsd">
    1.20 +      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    1.21 +    </None>
    1.22 +    <None Include="dtds\warfoundry-cats.xsd">
    1.23 +      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    1.24 +    </None>
    1.25    </ItemGroup>
    1.26    <ItemGroup>
    1.27      <Compile Include="api\Commands\CreateAndAddUnitCommand.cs" />
     2.1 --- a/api/Factories/Xml/WarFoundryXmlFactory.cs	Mon Mar 09 20:45:45 2009 +0000
     2.2 +++ b/api/Factories/Xml/WarFoundryXmlFactory.cs	Thu Mar 12 21:35:17 2009 +0000
     2.3 @@ -25,6 +25,7 @@
     2.4  	public class WarFoundryXmlFactory : AbstractNativeWarFoundryFactory
     2.5  	{
     2.6  		private static WarFoundryXmlFactory factory;
     2.7 +		private XmlReaderSettings settings;
     2.8  		private Dictionary<IWarFoundryObject, XmlDocument> extraData = new Dictionary<IWarFoundryObject, XmlDocument>();
     2.9  		private XmlResolver xmlResolver;
    2.10  
    2.11 @@ -266,12 +267,7 @@
    2.12  		protected XmlDocument CreateXmlDocumentFromStream(Stream stream)
    2.13  		{
    2.14  			XmlDocument doc = new XmlDocument();
    2.15 -			XmlReaderSettings settings = new XmlReaderSettings();
    2.16 -			settings.XmlResolver = xmlResolver;
    2.17 -			settings.ValidationType = ValidationType.DTD;
    2.18 -			settings.ProhibitDtd = false;
    2.19 -			settings.ValidationEventHandler+= new ValidationEventHandler(ValidationEventMethod);
    2.20 -			XmlReader reader = XmlReader.Create(stream, settings);
    2.21 +			XmlReader reader = XmlReader.Create(stream, GetReaderSettings());
    2.22  			
    2.23  			try
    2.24  			{
    2.25 @@ -289,6 +285,51 @@
    2.26  			}
    2.27  
    2.28  			return doc;
    2.29 +		}
    2.30 +		
    2.31 +				/// <summary>
    2.32 +		/// Lazy-getter for XML reader settings. May throw a <see cref="InvalidDataException"/> if there is a problem with the translation schema.
    2.33 +		/// </summary>
    2.34 +		/// <returns>
    2.35 +		/// A <see cref="XmlReaderSettings"/> with the default values for validating the translation document against the translation schema
    2.36 +		/// </returns>
    2.37 +		private XmlReaderSettings GetReaderSettings()
    2.38 +		{
    2.39 +			if (settings == null)
    2.40 +			{
    2.41 +				try
    2.42 +				{
    2.43 +					settings = new XmlReaderSettings();
    2.44 +					settings.ValidationType = ValidationType.Schema;
    2.45 +					settings.ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings;
    2.46 +					settings.ValidationEventHandler+= new ValidationEventHandler(ValidationEventMethod);
    2.47 +					XmlSchemaSet cache = new XmlSchemaSet();
    2.48 +					cache.Add("http://ibboard.co.uk/warfoundry/core", IBBoard.Constants.ExecutablePath + "/dtds/warfoundry-core.xsd");
    2.49 +					cache.Add("http://ibboard.co.uk/warfoundry/cats", IBBoard.Constants.ExecutablePath + "/dtds/warfoundry-cats.xsd");
    2.50 +					cache.Add("http://ibboard.co.uk/warfoundry/race", IBBoard.Constants.ExecutablePath + "/dtds/race.xsd");
    2.51 +					cache.Add("http://ibboard.co.uk/warfoundry/system", IBBoard.Constants.ExecutablePath + "/dtds/system.xsd");
    2.52 +					settings.Schemas.Add(cache);
    2.53 +				}
    2.54 +				catch (DirectoryNotFoundException ex)
    2.55 +				{
    2.56 +					throw new InvalidDataException("Problem validating schema for WarFoundry data: " + ex.Message, ex);
    2.57 +				}
    2.58 +				catch (XmlSchemaException ex)
    2.59 +				{
    2.60 +					throw new InvalidDataException("Problem validating schema for WarFoundry data: " + ex.Message, ex);
    2.61 +				}
    2.62 +				catch (XmlException ex)
    2.63 +				{
    2.64 +					throw new InvalidDataException("Problem reading data for schema: " + ex.Message, ex);
    2.65 +				}
    2.66 +			}
    2.67 +			
    2.68 +			return settings;
    2.69 +		}
    2.70 +		
    2.71 +		private void ValidationEventMethod(object sender, ValidationEventArgs e)
    2.72 +		{
    2.73 +			throw new InvalidDataException("Problem validating against schema for WarFoundry data: " + e.Exception.Message, e.Exception);
    2.74  		}
    2.75  
    2.76  		protected XmlDocument CreateXmlDocumentFromString(string xmlString)
    2.77 @@ -512,11 +553,5 @@
    2.78  			
    2.79  			return new EquipmentItem(id, name, cost, min, max, armourType, race);
    2.80  		}
    2.81 -		
    2.82 -		private void ValidationEventMethod(object sender, ValidationEventArgs e)
    2.83 -		{
    2.84 -			//TODO: Fire a validation failure event
    2.85 -    		LogNotifier.WarnFormat(GetType(), "Validation Error: {0}", e.Message);
    2.86 -		}
    2.87  	}
    2.88  }
    2.89 \ No newline at end of file
     3.1 --- a/api/WarFoundryLoader.cs	Mon Mar 09 20:45:45 2009 +0000
     3.2 +++ b/api/WarFoundryLoader.cs	Thu Mar 12 21:35:17 2009 +0000
     3.3 @@ -275,18 +275,26 @@
     3.4  			
     3.5  			foreach (FileInfo file in gameSystemFiles.Keys)
     3.6  			{
     3.7 +				FileLoadFailure failure = null;
     3.8 +				
     3.9  				try
    3.10  				{
    3.11  					bool loaded = LoadObject(file, gameSystemFiles[file]);
    3.12  	
    3.13  					if (!loaded)
    3.14  					{
    3.15 -						fails.Add(new FileLoadFailure(file, "FileLoadFailed", "Failed to load {0} as Race using {1}"));
    3.16 +						failure = new FileLoadFailure(file, "FileLoadFailed", "Failed to load {0} as Race using {1}");
    3.17  					}
    3.18  				}
    3.19  				catch (Exception ex)
    3.20  				{
    3.21 -					fails.Add(new FileLoadFailure(file, ex.Message));
    3.22 +					failure = new FileLoadFailure(file, ex.Message);
    3.23 +				}
    3.24 +						
    3.25 +				if (failure!=null)
    3.26 +				{
    3.27 +					fails.Add(failure);
    3.28 +					LogNotifier.Warn(GetType(), failure.Message);
    3.29  				}
    3.30  			}
    3.31  			
    3.32 @@ -299,18 +307,26 @@
    3.33  			
    3.34  			foreach (FileInfo file in raceFiles.Keys)
    3.35  			{
    3.36 +				FileLoadFailure failure = null;
    3.37 +				
    3.38  				try
    3.39  				{
    3.40  					bool loaded = LoadObject(file, raceFiles[file]);
    3.41  	
    3.42  					if (!loaded)
    3.43  					{
    3.44 -						fails.Add(new FileLoadFailure(file, "FileLoadFailed", "Failed to load {0} as Race using {1}"));
    3.45 +						failure = new FileLoadFailure(file, "FileLoadFailed", "Failed to load {0} as Race using {1}");
    3.46  					}
    3.47  				}
    3.48  				catch (Exception ex)
    3.49  				{
    3.50 -					fails.Add(new FileLoadFailure(file, ex.Message));
    3.51 +					failure = new FileLoadFailure(file, ex.Message);
    3.52 +				}
    3.53 +						
    3.54 +				if (failure!=null)
    3.55 +				{
    3.56 +					fails.Add(failure);
    3.57 +					LogNotifier.Warn(GetType(), failure.Message);
    3.58  				}
    3.59  			}
    3.60  			
     4.1 --- a/dtds/race.xsd	Mon Mar 09 20:45:45 2009 +0000
     4.2 +++ b/dtds/race.xsd	Thu Mar 12 21:35:17 2009 +0000
     4.3 @@ -28,7 +28,7 @@
     4.4      <xs:element name="requirements" type="requirementstype" />
     4.5      <xs:element name="contains" type="containstype" />
     4.6      <xs:element name="extraData" type="extradatatype" />
     4.7 -    <xs:element name="notes" type="xsd:string" />
     4.8 +    <xs:element name="notes" type="xs:string" />
     4.9    </xs:all>
    4.10    <xs:attribute name="id" type="xs:ID" />
    4.11    <xs:attribute name="typeName" type="xs:string" use="required"/>
    4.12 @@ -39,7 +39,7 @@
    4.13    <xs:attribute name="maxNumber" type="core:infiniteOrNonNegativeInteger" default="-1"/>
    4.14    <xs:attribute name="minSize" type="core:positiveInteger" default="5"/>
    4.15    <xs:attribute name="maxSize" type="core:infiniteOrNonNegativeInteger" default="-1"/>
    4.16 -  <xs:attribute name="baseSize" type="xsd:nonNegativeInteger" default="0"/>
    4.17 +  <xs:attribute name="baseSize" type="xs:nonNegativeInteger" default="0"/>
    4.18  </xs:complexType>
    4.19  <xs:complexType name="statstype">
    4.20    <xs:sequence>
    4.21 @@ -48,9 +48,10 @@
    4.22  </xs:complexType>
    4.23  <xs:complexType name="stattype">
    4.24    <xs:simpleContent>
    4.25 -    <xs:extension base="xs:string"/>
    4.26 +    <xs:extension base="xs:string">
    4.27 +      <xs:attribute name="name" type="xs:string" use="required"/>
    4.28 +    </xs:extension>
    4.29    </xs:simpleContent>
    4.30 -  <xs:attribute name="name" type="xs:string" use="required"/>
    4.31  </xs:complexType>
    4.32  <xs:complexType name="unitequipmenttype">
    4.33    <xs:sequence>
    4.34 @@ -89,9 +90,10 @@
    4.35  </xs:complexType>
    4.36  <xs:complexType name="requirementtype">
    4.37    <xs:simpleContent>
    4.38 -    <xs:extension base="xs:string"/>
    4.39 +    <xs:extension base="xs:string">
    4.40 +      <xs:attribute name="requirementName" type="xs:string" use="required"/>
    4.41 +    </xs:extension>
    4.42    </xs:simpleContent>
    4.43 -  <xs:attribute name="requirementName" type="xs:string" use="required"/>
    4.44  </xs:complexType>
    4.45  <xs:complexType name="containstype">
    4.46    <xs:sequence>
    4.47 @@ -108,9 +110,10 @@
    4.48  </xs:complexType>
    4.49  <xs:complexType name="extradatadatatype">
    4.50    <xs:simpleContent>
    4.51 -    <xs:extension base="xs:string"/>
    4.52 +    <xs:extension base="xs:string">
    4.53 +      <xs:attribute name="id" type="xs:ID" use="required"/>
    4.54 +    </xs:extension>
    4.55    </xs:simpleContent>
    4.56 -  <xs:attribute name="id" type="xs:ID" use="required"/>
    4.57  </xs:complexType>
    4.58  <xs:complexType name="equipmenttype">
    4.59    <xs:sequence>
    4.60 @@ -119,7 +122,7 @@
    4.61  </xs:complexType>
    4.62  <xs:complexType name="equipmentitemtype">
    4.63    <xs:all>
    4.64 -    <xs:element name="description" type="xsd:string" />
    4.65 +    <xs:element name="description" type="xs:string" />
    4.66    </xs:all>
    4.67    <xs:attribute name="id" type="xs:ID" use="required"/>
    4.68    <xs:attribute name="name" type="xs:string" use="required"/>
    4.69 @@ -132,7 +135,7 @@
    4.70  </xs:complexType>
    4.71  <xs:complexType name="equipmentitemtype">
    4.72    <xs:all>
    4.73 -    <xs:element name="description" type="xsd:string" />
    4.74 +    <xs:element name="description" type="xs:string" />
    4.75    </xs:all>
    4.76    <xs:attribute name="id" type="xs:ID" use="required"/>
    4.77    <xs:attribute name="name" type="xs:string" use="required"/>
    4.78 @@ -140,7 +143,7 @@
    4.79    <xs:attribute name="armoutType" type="armourtype" default="none"/>
    4.80  </xs:complexType>
    4.81  <xs:simpleType name="armourtype">
    4.82 -  <xs:restriction base="xsd:string">
    4.83 +  <xs:restriction base="xs:string">
    4.84      <xs:enumeration value="None"/>
    4.85      <xs:enumeration value="Shield"/>
    4.86      <xs:enumeration value="LightArmour"/>
    4.87 @@ -162,7 +165,7 @@
    4.88  </xs:complexType>
    4.89  <xs:complexType name="abilitytype">
    4.90    <xs:all>
    4.91 -    <xs:element name="description" type="xsd:string" />
    4.92 +    <xs:element name="description" type="xs:string" />
    4.93    </xs:all>
    4.94    <xs:attribute name="id" type="xs:ID" use="required"/>
    4.95    <xs:attribute name="name" type="xs:string" use="required"/>
     5.1 --- a/dtds/warfoundry-cats.xsd	Mon Mar 09 20:45:45 2009 +0000
     5.2 +++ b/dtds/warfoundry-cats.xsd	Thu Mar 12 21:35:17 2009 +0000
     5.3 @@ -1,6 +1,6 @@
     5.4  <?xml version="1.0"?>
     5.5  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://ibboard.co.uk/warfoundry/cats"
     5.6 -xmlns="http://ibboard.co.uk/warfoundry/cats"elementFormDefault="qualified">
     5.7 +xmlns="http://ibboard.co.uk/warfoundry/cats" elementFormDefault="qualified">
     5.8  <xs:complexType name="categoriestype">
     5.9    <xs:sequence>
    5.10      <xs:element name="cat" type="cattype" minOccurs="1" maxOccurs="unbounded"/>
     6.1 --- a/dtds/warfoundry-core.xsd	Mon Mar 09 20:45:45 2009 +0000
     6.2 +++ b/dtds/warfoundry-core.xsd	Thu Mar 12 21:35:17 2009 +0000
     6.3 @@ -1,6 +1,6 @@
     6.4  <?xml version="1.0"?>
     6.5  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://ibboard.co.uk/warfoundry/core"
     6.6 -xmlns="http://ibboard.co.uk/warfoundry/core"elementFormDefault="qualified">
     6.7 +xmlns="http://ibboard.co.uk/warfoundry/core" elementFormDefault="qualified">
     6.8  <xs:simpleType name="infiniteOrNonNegativeDecimal">
     6.9    <xs:restriction base="xs:decimal">
    6.10      <xs:minInclusive value="-1"/>