Skip to content

Instantly share code, notes, and snippets.

@Gelio
Created March 16, 2017 16:35
Show Gist options
  • Save Gelio/cb534b6612dd011f125a365230e90559 to your computer and use it in GitHub Desktop.
Save Gelio/cb534b6612dd011f125a365230e90559 to your computer and use it in GitHub Desktop.
Object oriented design XML cheatsheet (with snippets of C# to handle typical serialization behavior)
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
xmlns:bk="http://bookstore.mini.pw.edu.pl/"
>
<xsl:output method="html" indent="yes"/>
<xsl:template match="/bk:Bookstore">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Bookstore</title>
<style type="text/css">
<![CDATA[
table,td,th {
border: 1px solid black;
}
table {
margin-top: 1em;
}
.it {
background-color: #AAA;
}
.math {
background-color: #CCC;
}
]]>
</style>
</head>
<body>
<xsl:call-template name="publications" />
<xsl:call-template name="items" />
</body>
</html>
</xsl:template>
<xsl:template name="publications">
<table>
<tr>
<th>Author</th>
<th>Title</th>
<th>Type</th>
<th>Co-authors</th>
</tr>
<xsl:for-each select="bk:People/bk:Person">
<xsl:sort select="bk:Surname"/>
<xsl:variable name="person" select="current()" />
<xsl:for-each select="//bk:AuthorReference[@ref=$person/@id]">
<tr>
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="../@category = 'IT' or ../../@category = 'IT'">
it
</xsl:when>
<xsl:otherwise>
math
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<td>
<xsl:value-of select="$person"/>
</td>
<td>
<xsl:value-of select="../@title"/>
</td>
<td>
<xsl:value-of select="name(..)"/>
</td>
<td>
<xsl:value-of select="count(../bk:AuthorReference)-1"/>
</td>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template name="items">
<table>
<tr>
<th>Category</th>
<th>Type</th>
<th>Price</th>
</tr>
<xsl:for-each select="bk:Books/bk:Book | bk:Journals/bk:Journal">
<xsl:sort select="@price" data-type="number" order="descending"/>
<tr>
<td>
<xsl:value-of select="@category"/>
</td>
<td>
<xsl:value-of select="name(current())"/>
</td>
<td>
<xsl:value-of select="@price"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
// XSD schema
/*
In order to create a C# class from the schema paste the following into Pre-build events:
"$(SolutionDir)packages\Codaxy.Xsd2.0.9.9\tools\Xsd2.exe" "$(ProjectDir)Bookstore.xsd" /ns:Bookstore
Defining keys in schema (namespace is necessary)
<xs:key name="PERSON_ID">
<xs:selector xpath="b:People/b:Person" />
<xs:field xpath="@id" />
</xs:key>
<xs:keyref name="ATHBK_PERSON_ID" refer="b:PERSON_ID">
<xs:selector xpath="b:Books/b:Book/b:AuthorReference" />
<xs:field xpath="@ref" />
</xs:keyref>
<xs:keyref name="ATHART_PERSON_ID" refer="b:PERSON_ID">
<xs:selector xpath="b:Journals/b:Journal/b:Article/b:AuthorReference" />
<xs:field xpath="@ref" />
</xs:keyref>
*/
// Deserialization and validation against a schema file
using System.Xml.Linq;
using System.Xml.Schema;
using System.Xml.Serialization;
public static Bookstore Create(string xmlFilename)
{
string xmlData = Validate(xmlFilename);
XmlSerializer serializer = new XmlSerializer(typeof(Bookstore));
return (Bookstore)serializer.Deserialize(new StringReader(xmlData));
}
public static string Validate(string xmlFilename)
{
string xsdData = File.ReadAllText("Bookstore.xsd");
string xmlData = File.ReadAllText(xmlFilename);
XDocument document = XDocument.Parse(xmlData);
XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.Add(XmlSchema.Read(new StringReader(xsdData), (o, e) =>
{
if (e.Exception != null) throw e.Exception;
}));
document.Validate(schemaSet, (o, e) =>
{
if (e.Severity == XmlSeverityType.Error) throw e.Exception;
});
return xmlData;
}
// XSLT transformation
using System.Xml.Xsl;
static void Main(string[] args)
{
foreach (var arg in args)
{
try
{
Bookstore.Bookstore.Validate(arg);
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load("Bookstore.xslt");
transform.Transform(arg, arg.Replace(".xml",".html"));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
// JSON serialization
using Newtonsoft.Json;
string authorsAsJSON = JsonConvert.SerializeObject(new
{
authors = bookstore.People.Select(person =>
new
{
name = person.Name,
surname = person.Surname,
publications = bookstore.Publications.Where(pub => pub.AuthorReferenceID
.Contains(person.id))
.Select(pub => new { title = pub.title })
})
}, Formatting.Indented);
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:shop="http://www.mini.pw.edu.pl/~poLab/"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="html" indent="yes"/>
<xsl:template name="Product">
<td>
<xsl:number value="position()"/>
</td>
<td>
<xsl:value-of select="shop:Name"/>
</td>
<td>
<xsl:value-of select="format-number(shop:Price, '###,###.##')"/>
</td>
</xsl:template>
<xsl:template match="shop:Product1">
<tr>
<xsl:choose>
<xsl:when test="position() mod 4 = 1">
<xsl:attribute name="style">
background-color: cornflowerblue;
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="style">
background-color: gainsboro;
</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="Product" />
<td>
<xsl:value-of select="shop:Length"/>
</td>
<xsl:variable name="type" select="shop:ProductType" />
<td>
<xsl:value-of select="$type"/>
</td>
<td>
<xsl:choose>
<xsl:when test="contains($type, 'A') or contains($type, 'B')">
Yes
</xsl:when>
<xsl:otherwise>
No
</xsl:otherwise>
</xsl:choose>
</td>
</tr>
</xsl:template>
<xsl:template match="shop:Product2">
<tr>
<xsl:call-template name="Product" />
<td>
<xsl:value-of select="shop:Weight"/>
</td>
</tr>
</xsl:template>
<xsl:template match="/shop:Shop">
<html>
<head>
<title>Shop</title>
</head>
<body>
<div>
<h1>Product1</h1>
<table border="1">
<tr>
<th>Row</th>
<th>Name</th>
<th>Price</th>
<th>Length</th>
<th>Product Type</th>
<th>A or B</th>
</tr>
<tbody>
<xsl:apply-templates select="shop:Product1">
<xsl:sort select="shop:Price"/>
</xsl:apply-templates>
</tbody>
</table>
</div>
<div>
<h1>Product2</h1>
<table border="1">
<tr>
<th>Row</th>
<th>Name</th>
<th>Price</th>
<th>Weight</th>
</tr>
<tbody>
<xsl:apply-templates select="shop:Product2"/>
</tbody>
</table>
</div>
<div>
<h1>Static counter</h1>
<table border="1">
<tr>
<th>Product type</th>
<th>Count</th>
</tr>
<tbody>
<tr>
<td>A</td>
<td>
<xsl:value-of select="count(shop:Product1[shop:ProductType = 'A'])"/>
</td>
</tr>
<tr>
<td>B</td>
<td>
<xsl:value-of select="count(shop:Product1[shop:ProductType = 'B'])"/>
</td>
</tr>
</tbody>
</table>
</div>
<div>
<h1>Dynamic counter</h1>
<table border="1">
<tr>
<th>Product type</th>
<th>Count</th>
</tr>
<tbody>
<xsl:for-each select="shop:Product1/shop:ProductType[not(.=preceding::*)]">
<tr>
<td>
<xsl:value-of select="."/>
</td>
<td>
<xsl:value-of select="count(//shop:Product1[shop:ProductType = current()])" />
</td>
</tr>
</xsl:for-each>
</tbody>
</table>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment