Mercurial > repos > IBBoard.WarFoundry.API
changeset 409:dee3dcb72acf
Re #355: Add XML export format that can be transformed with an XSL
* Merge Clutch's XML/XSL API changes
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Thu, 25 Aug 2011 21:05:49 +0100 |
parents | cbe69734f48f (current diff) 2c52f0235774 (diff) |
children | 204e6de93232 |
files | |
diffstat | 4 files changed, 383 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/API/Exporters/WarFoundryXMLWithXSLExporter.cs Thu Aug 25 21:05:49 2011 +0100 @@ -0,0 +1,196 @@ +// This file (WarFoundryXmlWithXslExporter.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2011 Dan Kulinski +// +// The file and the library/program it is in are licensed and distributed, without warranty, under the GNU Affero GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; +using System.Xml.Xsl; +using System.Xml.XPath; +using System.Xml.Schema; +using IBBoard.Lang; +using IBBoard.Xml; +using IBBoard.WarFoundry.API.Objects; +using IBBoard.WarFoundry.API.Util; + +namespace IBBoard.WarFoundry.API.Exporters +{ + /// <summary> + /// Custom exporter that exports an army as an XML file with an XSLT applied + /// </summary> + public class WarFoundryXmlWithXslExporter : IWarFoundryExporter + { + private static WarFoundryXmlWithXslExporter exporter; + + // Return the default class associated with this exporter + public static WarFoundryXmlWithXslExporter GetDefault() + { + if (exporter == null) + { + exporter = new WarFoundryXmlWithXslExporter(); + } + + return exporter; + } + + private WarFoundryXmlWithXslExporter() + { + // Hide constructor + } + + // Write to file + public void ExportArmy(Army army, string path) + { + XmlDocument xmlDoc = BuildXml(army); + // Simple XML output settings + XmlWriterSettings xmlSettings = new XmlWriterSettings(); + xmlSettings.Indent = true; + xmlSettings.IndentChars = " "; + + // Write XML to file + using (XmlWriter writer = XmlWriter.Create(path, xmlSettings)) + { + xmlDoc.Save(writer); + writer.Flush(); + writer.Close(); + } + } + + // Write to file with transform + public void ExportArmyWithTransform(Army army, string savePath, string xslPath) + { + XmlDocument xmlDoc = BuildXml(army); + XslCompiledTransform xslTransform = new XslCompiledTransform(); + + xslTransform.Load(xslPath); + XmlWriter writer = XmlWriter.Create(savePath, xslTransform.OutputSettings); + xslTransform.Transform(xmlDoc, writer); + writer.Flush(); + writer.Close(); + } + + // Build the XML document to save or transform + private XmlDocument BuildXml(Army army) + { + XmlDocument armyList = new XmlDocument(); + + // Everything will be a child of the army element + XmlElement root = armyList.CreateElement("army"); + + // Basic army information + XmlElement armyRace = armyList.CreateElement("race"); + armyRace.InnerText = army.Race.Name; + root.AppendChild(armyRace); + + XmlElement armyName = armyList.CreateElement("name"); + armyName.InnerText = army.Name; + root.AppendChild(armyName); + + XmlElement armyAvailablePoints = armyList.CreateElement("pointsAvailable"); + armyAvailablePoints.InnerText = army.MaxPoints.ToString(); + root.AppendChild(armyAvailablePoints); + + XmlElement armyUsedPoints = armyList.CreateElement("pointsUsed"); + armyUsedPoints.InnerText = army.Points.ToString(); + root.AppendChild(armyUsedPoints); + + // Get Categories and interate through each + foreach(ArmyCategory cat in army.Categories) + { + if (cat.GetUnits().Length == 0) + continue; + XmlElement armyCategory = armyList.CreateElement("category"); + armyCategory.SetAttribute("type", cat.Name); + + + // Get units and iterate through each + foreach(Unit uni in cat.GetUnits()) + { + XmlElement armyUnit = armyList.CreateElement("unit"); + armyUnit.SetAttribute("name", uni.UnitType.Name); + + foreach (Stat[] stat in uni.UnitStatsArraysWithName) + { + XmlElement armyStatLine = armyList.CreateElement("statLine"); + foreach (Stat singleStat in stat) + { + XmlElement armyStat = armyList.CreateElement("stat"); + armyStat.SetAttribute("name", singleStat.ParentSlotName); + armyStat.SetAttribute("value", singleStat.SlotValueString); + armyStatLine.AppendChild(armyStat); + } + armyUnit.AppendChild(armyStatLine); + } + armyUnit.SetAttribute("points", uni.Points.ToString()); + armyUnit.SetAttribute("models", uni.Size.ToString()); + + foreach (UnitEquipmentItem equip in uni.GetEquipment()) + { + XmlElement armyEquipmentItem = armyList.CreateElement("equipmentItem"); + armyEquipmentItem.SetAttribute("name", equip.Name); + + int armyEquipAmount = 0; + + if (UnitEquipmentUtil.GetEquipmentAmount(uni, equip) == null) + { + armyEquipAmount = 0; + } + else + { + armyEquipAmount = (int)UnitEquipmentUtil.GetEquipmentAmount(uni, equip); + } + + if (UnitEquipmentUtil.GetEquipmentAmountIsRatio(uni, equip)) + { + float fraction = (float)(armyEquipAmount / 100.0); + armyEquipAmount = (int)(fraction * uni.Size); + } + + armyEquipmentItem.SetAttribute("count", armyEquipAmount.ToString()); + + armyUnit.AppendChild(armyEquipmentItem); + } + + foreach (Ability abil in uni.Abilities) + { + XmlElement armyAbilityItem = armyList.CreateElement("abilityItem"); + + armyAbilityItem.SetAttribute("name", abil.Name); + armyAbilityItem.SetAttribute("description", abil.Description); + + armyUnit.AppendChild(armyAbilityItem); + } + + armyCategory.AppendChild(armyUnit); + } + root.AppendChild(armyCategory); + } + + + + + // Append all Categories to the XML doc + + // Append tree to document + armyList.AppendChild(root); + + return armyList; + } + private string GetEquipmentAmountRatioTranslation(double amount, int number) + { + return Translation.GetTranslation("armyHtmlExportEquipAmountPercentage", "{0}% ({1})", amount, number); + } + + private string GetEquipmentAmountNumberTranslation(int amount) + { + return Translation.GetTranslation("armyHtmlExportEquipAmountNumber", "{0}", amount); + } + + private string GetEquipmentAmountAllTranslation(Unit unit) + { + return Translation.GetTranslation("armyHtmlExportEquipAmountAll", "all ({1})", 100, unit.Size); + } + } +}
--- a/IBBoard.WarFoundry.API.csproj Sun Aug 14 00:58:02 2011 +0000 +++ b/IBBoard.WarFoundry.API.csproj Thu Aug 25 21:05:49 2011 +0100 @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> @@ -60,6 +60,7 @@ <ItemGroup> <None Include="app.config" /> <None Include="COPYING" /> + <Compile Include="API\Exporters\WarFoundryXMLWithXSLExporter.cs" /> <Compile Include="AssemblyInfo.cs" /> <None Include="schemas\army.xsd"> <Gettext-ScanForTranslations>false</Gettext-ScanForTranslations> @@ -196,6 +197,14 @@ <Name>ICSharpCode.SharpZLib</Name> </ProjectReference> </ItemGroup> + <ItemGroup> + <Content Include="xsl\default_html.xsl"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + <Content Include="xsl\unitcard.xsl"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + </ItemGroup> <ProjectExtensions> <MonoDevelop> <Properties>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xsl/default_html.xsl Thu Aug 25 21:05:49 2011 +0100 @@ -0,0 +1,59 @@ +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <xsl:output doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" method="html" indent="yes" omit-xml-declaration="yes"/> +<xsl:template match="/"> + <html> + <head> + <style> + table, th, td { border: 1px solid #000; border-spacing: 0; border-collapse: collapse; margin: 0 } + table table { width: 100%; border-width: 0; margin: -2px } + table table td { border-width:0 1px } + </style> + <title> + <xsl:value-of select="/army/name"/> + </title> + </head> + <body> + <div id="armyInfo"> + <h1> + <xsl:value-of select="/army/name"/> - <xsl:value-of select="/army/pointsUsed"/>pts + </h1> + <xsl:for-each select="/army/category"> + <table> + <xsl:for-each select="./unit/statLine[1]"> + <tr> + <xsl:for-each select="./stat"> + <td> + <xsl:value-of select="./@name"/> + </td> + </xsl:for-each> + <td>Notes</td> + <td>Points</td> + </tr> + </xsl:for-each> + <xsl:for-each select="./unit/statLine"> + <tr> + <xsl:for-each select="./stat"> + <td> + <xsl:value-of select="./@value"/> + </td> + </xsl:for-each> + <td> + <xsl:for-each select="../equipmentItem"> + <xsl:value-of select="./@name"/> (<xsl:value-of select="./@count"/>), + </xsl:for-each> + <xsl:for-each select="../abilityItem"> + <xsl:value-of select="./@name"/> (<xsl:value-of select="./@description"/>), + </xsl:for-each> + </td> + <td> + <xsl:value-of select="../@points"/> + </td> + </tr> + </xsl:for-each> + </table> + </xsl:for-each> + </div> + </body> + </html> +</xsl:template> +</xsl:stylesheet> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xsl/unitcard.xsl Thu Aug 25 21:05:49 2011 +0100 @@ -0,0 +1,118 @@ +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + <xsl:output doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" method="html" indent="yes" omit-xml-declaration="yes"/> + <xsl:variable name="lower">abcdefghijklmnopqrstuvwxyz</xsl:variable> + <xsl:variable name="upper">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable> + <xsl:template match="/"> + <html> + <head> + <title> + <xsl:value-of select="/army/name"/> - Created in WarFoundry + </title> + <style media="all"> + div#armyInfo { font-size: x-large; width: 100%; margin-bottom: 2em; } + div.unitcard { border: 1px solid black; width: 75%; margin-bottom: 2em; } + div.unitcard table.title { width: 100%; } + div.unitcard table.title th { background-color: #999999; } + table.stats { border-collapse: collapse; width: 100%;} + table.lists { padding: 0px; margins: 0px; border: 1px solid black; width: 100%} + table.lists th { font-size: small; font-variant: small-caps; text-align: left; } + table.lists td { width: 45%; } + ul.equipmentList { font-size: small; display: inline; list-style-type: none; } + ul.abilityList { font-size: small; display: inline; list-style-type: none; } + </style> + <style media="print"> + div.unitcard { page-break-inside: avoid; } + div.specialrules { page-break-inside: avoid; } + div.pagebreak { page-break-after: always; display: none; } + </style> + </head> + <body> + <div id="armyInfo"> + Name: <xsl:value-of select="/army/name"/> <br /> + Points: <xsl:value-of select="/army/pointsUsed"/> of + <xsl:value-of select="/army/pointsAvailable"/> + </div> + <xsl:for-each select="/army/category"> + <xsl:for-each select="./unit"> + <div class="unitcard"> + <table class="title"> + <th align="left" width="50%"> + <xsl:value-of select="../@type"/>:<xsl:value-of select="./@name"/> + </th> + <th width="25%"> + Models: <xsl:value-of select="sum(.//@models)"/> + </th> + <th width="25%"> + Points: <xsl:value-of select="./@points"/> + </th> + </table> + <table class="stats" border="1"> + <xsl:for-each select="./statLine[1]"> + <tr> + <xsl:for-each select="./stat"> + <td> + <b> + <xsl:value-of select="translate(./@name,$lower,$upper)"/> + </b> + </td> + </xsl:for-each> + </tr> + </xsl:for-each> + <xsl:for-each select="./statLine"> + <tr> + <xsl:for-each select="./stat"> + <td> + <xsl:value-of select="./@value"/> + </td> + </xsl:for-each> + </tr> + </xsl:for-each> + </table> + <table class="lists"> + <tr> + <th> + Equipment + </th> + <th> + Abilities + </th> + </tr> + <tr> + <td> + <ul class="equipmentList"> + <xsl:for-each select="./equipmentItem"> + <li> + <xsl:value-of select="./@name"/> (<xsl:value-of select="./@count"/>) + </li> + </xsl:for-each> + </ul> + </td> + <td> + <ul class="abilityList"> + <xsl:for-each select="./abilityItem"> + <li> + <xsl:value-of select="./@name"/> + </li> + </xsl:for-each> + </ul> + </td> + </tr> + </table> + </div> + </xsl:for-each> + </xsl:for-each> + <div class="pagebreak"></div> + <div class="specialrules"> + <h2>Special Rules</h2> + <ul class="abilityDescriptions"> + <xsl:for-each select='//abilityItem[not(@name = preceding::abilityItem/@name)]'> + <li> + <xsl:value-of select='@name'/> - <xsl:value-of select='@description'/> + </li> + </xsl:for-each> + </ul> + </div> + </body> + </html> + </xsl:template> +</xsl:stylesheet> \ No newline at end of file