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 2c52f0235774
children 204e6de93232
files
diffstat 4 files changed, 383 insertions(+), 1 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/API/Exporters/WarFoundryXMLWithXSLExporter.cs	Thu Aug 25 21:05:49 2011 +0100
     1.3 @@ -0,0 +1,196 @@
     1.4 +// This file (WarFoundryXmlWithXslExporter.cs) is a part of the IBBoard.WarFoundry.API project and is copyright 2011 Dan Kulinski
     1.5 +// 
     1.6 +// 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.
     1.7 +
     1.8 +using System;
     1.9 +using System.Collections.Generic;
    1.10 +using System.IO;
    1.11 +using System.Text;
    1.12 +using System.Xml;
    1.13 +using System.Xml.Xsl;
    1.14 +using System.Xml.XPath;
    1.15 +using System.Xml.Schema;
    1.16 +using IBBoard.Lang;
    1.17 +using IBBoard.Xml;
    1.18 +using IBBoard.WarFoundry.API.Objects;
    1.19 +using IBBoard.WarFoundry.API.Util;
    1.20 +
    1.21 +namespace IBBoard.WarFoundry.API.Exporters
    1.22 +{
    1.23 +	/// <summary>
    1.24 +	/// Custom exporter that exports an army as an XML file with an XSLT applied
    1.25 +	/// </summary>
    1.26 +    public class WarFoundryXmlWithXslExporter : IWarFoundryExporter
    1.27 +	{
    1.28 +        private static WarFoundryXmlWithXslExporter exporter;
    1.29 +
    1.30 +        // Return the default class associated with this exporter
    1.31 +        public static WarFoundryXmlWithXslExporter GetDefault()
    1.32 +        {
    1.33 +            if (exporter == null)
    1.34 +            {
    1.35 +                exporter = new WarFoundryXmlWithXslExporter();
    1.36 +            }
    1.37 +
    1.38 +            return exporter;
    1.39 +        }
    1.40 +
    1.41 +        private WarFoundryXmlWithXslExporter()
    1.42 +        {
    1.43 +            // Hide constructor
    1.44 +        }
    1.45 +
    1.46 +        // Write to file
    1.47 +        public void ExportArmy(Army army, string path)
    1.48 +        {
    1.49 +            XmlDocument xmlDoc = BuildXml(army);
    1.50 +            // Simple XML output settings
    1.51 +            XmlWriterSettings xmlSettings = new XmlWriterSettings();
    1.52 +            xmlSettings.Indent = true;
    1.53 +            xmlSettings.IndentChars = "  ";
    1.54 +
    1.55 +            // Write XML to file
    1.56 +            using (XmlWriter writer = XmlWriter.Create(path, xmlSettings))
    1.57 +            {
    1.58 +                xmlDoc.Save(writer);
    1.59 +                writer.Flush();
    1.60 +                writer.Close();
    1.61 +            }
    1.62 +        }
    1.63 +
    1.64 +        // Write to file with transform
    1.65 +        public void ExportArmyWithTransform(Army army, string savePath, string xslPath)
    1.66 +        {
    1.67 +            XmlDocument xmlDoc = BuildXml(army);
    1.68 +            XslCompiledTransform xslTransform = new XslCompiledTransform();
    1.69 +
    1.70 +            xslTransform.Load(xslPath);
    1.71 +            XmlWriter writer = XmlWriter.Create(savePath, xslTransform.OutputSettings);
    1.72 +            xslTransform.Transform(xmlDoc, writer);
    1.73 +            writer.Flush();
    1.74 +            writer.Close();
    1.75 +        }
    1.76 +        
    1.77 +        // Build the XML document to save or transform
    1.78 +        private XmlDocument BuildXml(Army army)
    1.79 +        {
    1.80 +            XmlDocument armyList = new XmlDocument();
    1.81 +           
    1.82 +            // Everything will be a child of the army element
    1.83 +            XmlElement root = armyList.CreateElement("army");
    1.84 +
    1.85 +            // Basic army information
    1.86 +            XmlElement armyRace = armyList.CreateElement("race");
    1.87 +            armyRace.InnerText = army.Race.Name;
    1.88 +            root.AppendChild(armyRace);
    1.89 +
    1.90 +            XmlElement armyName = armyList.CreateElement("name");
    1.91 +            armyName.InnerText = army.Name;
    1.92 +            root.AppendChild(armyName);
    1.93 +
    1.94 +            XmlElement armyAvailablePoints = armyList.CreateElement("pointsAvailable");
    1.95 +            armyAvailablePoints.InnerText = army.MaxPoints.ToString();
    1.96 +            root.AppendChild(armyAvailablePoints);
    1.97 +
    1.98 +            XmlElement armyUsedPoints = armyList.CreateElement("pointsUsed");
    1.99 +            armyUsedPoints.InnerText = army.Points.ToString();
   1.100 +            root.AppendChild(armyUsedPoints);
   1.101 +
   1.102 +            // Get Categories and interate through each
   1.103 +            foreach(ArmyCategory cat in army.Categories)
   1.104 +            {
   1.105 +                if (cat.GetUnits().Length == 0)
   1.106 +                    continue;
   1.107 +                XmlElement armyCategory = armyList.CreateElement("category");
   1.108 +                armyCategory.SetAttribute("type", cat.Name);
   1.109 +                
   1.110 +
   1.111 +                // Get units and iterate through each
   1.112 +                foreach(Unit uni in cat.GetUnits())
   1.113 +                {
   1.114 +                    XmlElement armyUnit = armyList.CreateElement("unit");
   1.115 +                    armyUnit.SetAttribute("name", uni.UnitType.Name);
   1.116 +
   1.117 +                    foreach (Stat[] stat in uni.UnitStatsArraysWithName)
   1.118 +                    {
   1.119 +                        XmlElement armyStatLine = armyList.CreateElement("statLine");
   1.120 +                        foreach (Stat singleStat in stat)
   1.121 +                        {
   1.122 +                            XmlElement armyStat = armyList.CreateElement("stat");
   1.123 +                            armyStat.SetAttribute("name", singleStat.ParentSlotName);
   1.124 +                            armyStat.SetAttribute("value", singleStat.SlotValueString);
   1.125 +                            armyStatLine.AppendChild(armyStat);
   1.126 +                        }
   1.127 +                        armyUnit.AppendChild(armyStatLine);
   1.128 +                    }
   1.129 +                    armyUnit.SetAttribute("points", uni.Points.ToString());
   1.130 +                    armyUnit.SetAttribute("models", uni.Size.ToString());
   1.131 +
   1.132 +                    foreach (UnitEquipmentItem equip in uni.GetEquipment())
   1.133 +                    {
   1.134 +                        XmlElement armyEquipmentItem = armyList.CreateElement("equipmentItem");
   1.135 +                        armyEquipmentItem.SetAttribute("name", equip.Name);
   1.136 +
   1.137 +                        int armyEquipAmount = 0;
   1.138 +
   1.139 +                        if (UnitEquipmentUtil.GetEquipmentAmount(uni, equip) == null)
   1.140 +                        {
   1.141 +                            armyEquipAmount = 0;
   1.142 +                        }
   1.143 +                        else
   1.144 +                        {
   1.145 +                            armyEquipAmount = (int)UnitEquipmentUtil.GetEquipmentAmount(uni, equip);
   1.146 +                        }
   1.147 +                        
   1.148 +                        if (UnitEquipmentUtil.GetEquipmentAmountIsRatio(uni, equip))
   1.149 +                        {
   1.150 +                            float fraction = (float)(armyEquipAmount / 100.0);
   1.151 +                            armyEquipAmount = (int)(fraction * uni.Size);
   1.152 +                        }
   1.153 +
   1.154 +                        armyEquipmentItem.SetAttribute("count", armyEquipAmount.ToString());
   1.155 +                       
   1.156 +                        armyUnit.AppendChild(armyEquipmentItem);
   1.157 +                    }
   1.158 +
   1.159 +                    foreach (Ability abil in uni.Abilities)
   1.160 +                    {
   1.161 +                        XmlElement armyAbilityItem = armyList.CreateElement("abilityItem");
   1.162 +
   1.163 +                        armyAbilityItem.SetAttribute("name", abil.Name);
   1.164 +                        armyAbilityItem.SetAttribute("description", abil.Description);
   1.165 +
   1.166 +                        armyUnit.AppendChild(armyAbilityItem);
   1.167 +                    }
   1.168 +
   1.169 +                    armyCategory.AppendChild(armyUnit);
   1.170 +                }
   1.171 +                root.AppendChild(armyCategory);
   1.172 +            }
   1.173 +
   1.174 +           
   1.175 +           
   1.176 +
   1.177 +            // Append all Categories to the XML doc
   1.178 +
   1.179 +            // Append tree to document
   1.180 +            armyList.AppendChild(root);
   1.181 +
   1.182 +            return armyList;
   1.183 +        }
   1.184 +        private string GetEquipmentAmountRatioTranslation(double amount, int number)
   1.185 +        {
   1.186 +            return Translation.GetTranslation("armyHtmlExportEquipAmountPercentage", "{0}% ({1})", amount, number);
   1.187 +        }
   1.188 +
   1.189 +        private string GetEquipmentAmountNumberTranslation(int amount)
   1.190 +        {
   1.191 +            return Translation.GetTranslation("armyHtmlExportEquipAmountNumber", "{0}", amount);
   1.192 +        }
   1.193 +
   1.194 +        private string GetEquipmentAmountAllTranslation(Unit unit)
   1.195 +        {
   1.196 +            return Translation.GetTranslation("armyHtmlExportEquipAmountAll", "all ({1})", 100, unit.Size);
   1.197 +        }
   1.198 +    }
   1.199 +}
     2.1 --- a/IBBoard.WarFoundry.API.csproj	Sun Aug 14 00:58:02 2011 +0000
     2.2 +++ b/IBBoard.WarFoundry.API.csproj	Thu Aug 25 21:05:49 2011 +0100
     2.3 @@ -1,4 +1,4 @@
     2.4 -<?xml version="1.0" encoding="utf-8"?>
     2.5 +<?xml version="1.0" encoding="utf-8"?>
     2.6  <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
     2.7    <PropertyGroup>
     2.8      <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     2.9 @@ -60,6 +60,7 @@
    2.10    <ItemGroup>
    2.11      <None Include="app.config" />
    2.12      <None Include="COPYING" />
    2.13 +    <Compile Include="API\Exporters\WarFoundryXMLWithXSLExporter.cs" />
    2.14      <Compile Include="AssemblyInfo.cs" />
    2.15      <None Include="schemas\army.xsd">
    2.16        <Gettext-ScanForTranslations>false</Gettext-ScanForTranslations>
    2.17 @@ -196,6 +197,14 @@
    2.18        <Name>ICSharpCode.SharpZLib</Name>
    2.19      </ProjectReference>
    2.20    </ItemGroup>
    2.21 +  <ItemGroup>
    2.22 +    <Content Include="xsl\default_html.xsl">
    2.23 +      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    2.24 +    </Content>
    2.25 +    <Content Include="xsl\unitcard.xsl">
    2.26 +      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    2.27 +    </Content>
    2.28 +  </ItemGroup>
    2.29    <ProjectExtensions>
    2.30      <MonoDevelop>
    2.31        <Properties>
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xsl/default_html.xsl	Thu Aug 25 21:05:49 2011 +0100
     3.3 @@ -0,0 +1,59 @@
     3.4 +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     3.5 +  <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"/>
     3.6 +<xsl:template match="/">
     3.7 +  <html>
     3.8 +    <head>
     3.9 +      <style>
    3.10 +        table, th, td { border: 1px solid #000; border-spacing: 0; border-collapse: collapse; margin: 0 }
    3.11 +        table table { width: 100%; border-width: 0; margin: -2px }
    3.12 +        table table td { border-width:0 1px }
    3.13 +      </style>
    3.14 +      <title>
    3.15 +        <xsl:value-of select="/army/name"/>
    3.16 +      </title>
    3.17 +    </head>
    3.18 +    <body>
    3.19 +      <div id="armyInfo">
    3.20 +        <h1>
    3.21 +          <xsl:value-of select="/army/name"/> - <xsl:value-of select="/army/pointsUsed"/>pts
    3.22 +        </h1>
    3.23 +        <xsl:for-each select="/army/category">
    3.24 +          <table>
    3.25 +            <xsl:for-each select="./unit/statLine[1]">
    3.26 +              <tr>
    3.27 +                <xsl:for-each select="./stat">
    3.28 +                  <td>
    3.29 +                    <xsl:value-of select="./@name"/>
    3.30 +                  </td>
    3.31 +                </xsl:for-each>
    3.32 +                <td>Notes</td>
    3.33 +                <td>Points</td>
    3.34 +              </tr>
    3.35 +            </xsl:for-each>
    3.36 +            <xsl:for-each select="./unit/statLine">
    3.37 +              <tr>
    3.38 +                <xsl:for-each select="./stat">
    3.39 +                  <td>
    3.40 +                    <xsl:value-of select="./@value"/>
    3.41 +                  </td>
    3.42 +                </xsl:for-each>
    3.43 +                <td>
    3.44 +                  <xsl:for-each select="../equipmentItem">
    3.45 +                    <xsl:value-of select="./@name"/> (<xsl:value-of select="./@count"/>),
    3.46 +                  </xsl:for-each>
    3.47 +                  <xsl:for-each select="../abilityItem">
    3.48 +                    <xsl:value-of select="./@name"/> (<xsl:value-of select="./@description"/>),
    3.49 +                 </xsl:for-each>
    3.50 +                </td>
    3.51 +                <td>
    3.52 +                  <xsl:value-of select="../@points"/>
    3.53 +                </td>
    3.54 +              </tr>
    3.55 +            </xsl:for-each>
    3.56 +          </table>
    3.57 +        </xsl:for-each>
    3.58 +      </div>
    3.59 +    </body>
    3.60 +  </html>
    3.61 +</xsl:template>
    3.62 +</xsl:stylesheet>
    3.63 \ No newline at end of file
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/xsl/unitcard.xsl	Thu Aug 25 21:05:49 2011 +0100
     4.3 @@ -0,0 +1,118 @@
     4.4 +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     4.5 +  <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"/>
     4.6 +  <xsl:variable name="lower">abcdefghijklmnopqrstuvwxyz</xsl:variable>
     4.7 +  <xsl:variable name="upper">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
     4.8 +  <xsl:template match="/">
     4.9 +    <html>
    4.10 +      <head>
    4.11 +        <title>
    4.12 +          <xsl:value-of select="/army/name"/> - Created in WarFoundry
    4.13 +        </title>
    4.14 +        <style media="all">
    4.15 +          div#armyInfo { font-size: x-large; width: 100%; margin-bottom: 2em; }
    4.16 +          div.unitcard { border: 1px solid black; width: 75%; margin-bottom: 2em; }
    4.17 +          div.unitcard table.title { width: 100%; }
    4.18 +          div.unitcard table.title th { background-color: #999999; }
    4.19 +          table.stats { border-collapse: collapse; width: 100%;}
    4.20 +          table.lists { padding: 0px; margins: 0px; border: 1px solid black; width: 100%}
    4.21 +          table.lists th { font-size: small; font-variant: small-caps; text-align: left; }
    4.22 +          table.lists td { width: 45%; }
    4.23 +          ul.equipmentList { font-size: small; display: inline; list-style-type: none; }
    4.24 +          ul.abilityList { font-size: small; display: inline; list-style-type: none; }
    4.25 +        </style>
    4.26 +        <style media="print">
    4.27 +          div.unitcard { page-break-inside: avoid; }
    4.28 +          div.specialrules { page-break-inside: avoid; }
    4.29 +          div.pagebreak { page-break-after: always; display: none; }
    4.30 +        </style>
    4.31 +      </head>
    4.32 +      <body>
    4.33 +        <div id="armyInfo">
    4.34 +          Name: <xsl:value-of select="/army/name"/> <br />
    4.35 +          Points: <xsl:value-of select="/army/pointsUsed"/> of
    4.36 +          <xsl:value-of select="/army/pointsAvailable"/>
    4.37 +        </div>
    4.38 +        <xsl:for-each select="/army/category">
    4.39 +          <xsl:for-each select="./unit">
    4.40 +            <div class="unitcard">
    4.41 +              <table class="title">
    4.42 +                <th align="left" width="50%">
    4.43 +                  <xsl:value-of select="../@type"/>:<xsl:value-of select="./@name"/>
    4.44 +                </th>
    4.45 +                <th width="25%">
    4.46 +                  Models: <xsl:value-of select="sum(.//@models)"/>
    4.47 +                </th>
    4.48 +                <th width="25%">
    4.49 +                  Points: <xsl:value-of select="./@points"/>
    4.50 +                </th>
    4.51 +              </table>
    4.52 +              <table class="stats" border="1">
    4.53 +                <xsl:for-each select="./statLine[1]">
    4.54 +                  <tr>
    4.55 +                    <xsl:for-each select="./stat">
    4.56 +                      <td>
    4.57 +                        <b>
    4.58 +                          <xsl:value-of select="translate(./@name,$lower,$upper)"/>
    4.59 +                        </b>
    4.60 +                      </td>
    4.61 +                    </xsl:for-each>
    4.62 +                  </tr>
    4.63 +                </xsl:for-each>
    4.64 +                <xsl:for-each select="./statLine">
    4.65 +                  <tr>
    4.66 +                    <xsl:for-each select="./stat">
    4.67 +                      <td>
    4.68 +                        <xsl:value-of select="./@value"/>
    4.69 +                      </td>
    4.70 +                    </xsl:for-each>
    4.71 +                  </tr>
    4.72 +                </xsl:for-each>
    4.73 +              </table>
    4.74 +              <table class="lists">
    4.75 +                <tr>
    4.76 +                  <th>
    4.77 +                    Equipment
    4.78 +                  </th>
    4.79 +                  <th>
    4.80 +                    Abilities
    4.81 +                  </th>
    4.82 +                </tr>
    4.83 +                <tr>
    4.84 +                  <td>
    4.85 +                    <ul class="equipmentList">
    4.86 +                      <xsl:for-each select="./equipmentItem">
    4.87 +                        <li>
    4.88 +                          <xsl:value-of select="./@name"/> (<xsl:value-of select="./@count"/>)
    4.89 +                        </li>
    4.90 +                      </xsl:for-each>
    4.91 +                    </ul>
    4.92 +                  </td>
    4.93 +                  <td>
    4.94 +                    <ul class="abilityList">
    4.95 +                      <xsl:for-each select="./abilityItem">
    4.96 +                        <li>
    4.97 +                          <xsl:value-of select="./@name"/>
    4.98 +                        </li>
    4.99 +                      </xsl:for-each>
   4.100 +                    </ul>
   4.101 +                  </td>
   4.102 +                </tr>
   4.103 +              </table>
   4.104 +            </div>
   4.105 +          </xsl:for-each>
   4.106 +        </xsl:for-each>
   4.107 +        <div class="pagebreak"></div>
   4.108 +        <div class="specialrules">
   4.109 +          <h2>Special Rules</h2>
   4.110 +          <ul class="abilityDescriptions">
   4.111 +            <xsl:for-each select='//abilityItem[not(@name = preceding::abilityItem/@name)]'>
   4.112 +              <li>
   4.113 +                <xsl:value-of select='@name'/> - <xsl:value-of select='@description'/>
   4.114 +              </li>
   4.115 +            </xsl:for-each>
   4.116 +          </ul>
   4.117 +        </div>
   4.118 +      </body>
   4.119 +    </html>
   4.120 +  </xsl:template>
   4.121 +</xsl:stylesheet>
   4.122 \ No newline at end of file