Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions xslt/generate_md_report.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="http://www.radical.sexy"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
exclude-result-prefixes="xs my map"
version="2.0"
>
<xsl:import href="numbering.xslt" />
<xsl:import href="localisation.xslt" />
<xsl:import href="md_placeholders.xslt" />
<!-- Includes functions calculatePersonDays, generateTargets
Includes template VersionNumber -->
<xsl:import href="md_auto.xslt" />
<!-- Includes Markdown formatting -->
<xsl:import href="md_formatting.xslt" />
<xsl:include href="functions_params_vars.xslt" />

<xsl:preserve-space elements="pre code" />
<xsl:strip-space elements="*" />
<xsl:output method="text" encoding="UTF-8" indent="no" />

<xsl:param name="NUMBERING" select="true()" />

<!-- Dynamically skip identifiers from the report -->
<xsl:variable
name="skip-ids"
select="
if (unparsed-text-available('../exclude-ids.txt'))
then tokenize(unparsed-text('../exclude-ids.txt'), '\s*,\s*|\s+')
else ()
"
/>

<!-- Text node normalization -->
<xsl:template match="text()[normalize-space()][not(ancestor::pre)]">
<xsl:value-of select="normalize-space(.)" />
<xsl:if test="following-sibling::text()[normalize-space()][1]">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:template>

<!-- Root -->
<xsl:template match="/">
<xsl:apply-templates select="/*/section | /*/appendix" />
</xsl:template>

<!-- Sections/Appendices -->
<xsl:template match="section | appendix">
<xsl:if test="not(@id = $skip-ids)">
<xsl:apply-templates select="node()" />
</xsl:if>
</xsl:template>

<!-- Findings -->
<xsl:template match="finding">
<xsl:text>&#10;### </xsl:text>
<xsl:value-of select="@number" />
<xsl:text> - </xsl:text>
<xsl:value-of select="title" />
<xsl:text>&#10;&#10;</xsl:text>

<xsl:variable
name="info"
select="map {
'Type': normalize-space(@type),
'Identifier': @id,
'Threat Level': @threatLevel
}"
/>
<xsl:for-each select="map:keys($info)">
<xsl:call-template name="finding-section">
<xsl:with-param name="label" select="." />
<xsl:with-param name="value" select="$info(.)" />
</xsl:call-template>
</xsl:for-each>

<xsl:variable
name="sectionLabels"
select="map {
'description': 'Description',
'technicaldescription': 'Technical Description',
'update': 'Update',
'impact': 'Impact',
'recommendation': 'Recommendation'
}"
/>
<xsl:for-each
select="description|technicaldescription|update|impact|recommendation"
>
<xsl:text>&#10;#### </xsl:text>
<xsl:value-of select="$sectionLabels(local-name())" />
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates />
</xsl:for-each>
</xsl:template>

<xsl:template name="finding-section">
<xsl:param name="label" />
<xsl:param name="value" />
<xsl:text>&#10;#### </xsl:text>
<xsl:value-of select="$label" />
<xsl:text>&#10;</xsl:text>
<xsl:value-of select="$value" />
<xsl:text>&#10;</xsl:text>
</xsl:template>
</xsl:stylesheet>
61 changes: 61 additions & 0 deletions xslt/md_auto.xslt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="http://www.radical.sexy"
exclude-result-prefixes="xs my"
version="2.0"
>

<!-- Calculates person-days from min/max durations -->
<xsl:function name="my:calculatePersonDays" as="xs:string">
<xsl:param name="context" as="element()" />
<xsl:variable
name="durations"
select="$context//entry[@type='service']/dh"
/>
<xsl:variable name="min" select="sum($durations/min)" />
<xsl:variable name="max" select="sum($durations/max)" />
<xsl:if test="$min != $max">
<xsl:value-of select="$min div 8" />
<xsl:text> - </xsl:text>
<xsl:value-of select="$max div 8" />
</xsl:if>
<xsl:if test="$min = $max">
<xsl:value-of select="$min div 8" />
</xsl:if>
</xsl:function>

<!-- Generates target list -->
<xsl:function name="my:generateTargets" as="xs:string">
<xsl:param name="context" as="element()" />
<xsl:text>&#10;</xsl:text>
<xsl:for-each select="$context//targets/target">
<xsl:text>- </xsl:text>
<xsl:apply-templates select="." />
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
</xsl:function>

<!-- Generates version number (auto or explicit) -->
<xsl:template name="VersionNumber">
<xsl:param name="number" select="@number" />
<xsl:choose>
<!-- if value is auto, do some autonumbering magic -->
<xsl:when test="string(@number) = 'auto'">
0.
<xsl:number
count="version"
level="multiple"
format="{$AUTO_NUMBERING_FORMAT}"
/>
<!-- this is really unrobust :D - todo: follow fixed numbering if provided -->
</xsl:when>
<xsl:otherwise>
<!-- just plop down the value -->
<!-- todo: guard numbering format in schema -->
<xsl:value-of select="@number" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
141 changes: 141 additions & 0 deletions xslt/md_formatting.xslt
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="http://www.radical.sexy"
exclude-result-prefixes="xs my"
version="2.0"
>

<!-- Adds a space before punctuation or at end of text -->
<xsl:function name="my:addSpaceIfNeeded" as="xs:string">
<xsl:param name="node" as="element()" />
<xsl:variable
name="next"
select="
$node/following-sibling::node()
[not(self::comment() or self::processing-instruction())]
[normalize-space()][1]
"
/>
<xsl:sequence
select="
if (empty($next)) then ''
else if ($next[self::text()][matches(., '^[,.\)]')]) then ''
else ' '
"
/>
</xsl:function>

<!-- Adds a space before an element if not preceded by (, [, <, or whitespace -->
<xsl:function name="my:addSpaceBeforeIfNeeded" as="xs:string">
<xsl:param name="node" as="element()" />
<xsl:variable
name="prev"
select="
$node/preceding-sibling::node()
[not(self::comment() or self::processing-instruction())]
[normalize-space()][1]
"
/>
<xsl:sequence
select="
if (empty($prev)) then ''
else if ($prev[self::text()][matches(., '(\s|[(\[{])$')]) then ''
else ' '
"
/>
</xsl:function>

<!-- Headings -->
<xsl:template match="title">
<xsl:variable
name="level"
select="count(ancestor::section | ancestor::appendix) + 1"
/>
<xsl:if test="count(preceding::title) &gt; 0">
<xsl:text>&#10;</xsl:text>
</xsl:if>
<xsl:text>#</xsl:text>
<xsl:for-each select="1 to $level - 1">
<xsl:text>#</xsl:text>
</xsl:for-each>
<xsl:text> </xsl:text>
<xsl:value-of select="." />
<xsl:text>&#10;</xsl:text>
</xsl:template>

<!-- Inline elements -->
<xsl:template match="br">
<xsl:text>&#10;&#10;</xsl:text>
</xsl:template>
<xsl:template match="p">
<xsl:apply-templates />
<xsl:text>&#10;</xsl:text>
</xsl:template>

<xsl:template match="a">
<xsl:value-of select="my:addSpaceBeforeIfNeeded(.)" />
<xsl:text>[</xsl:text>
<xsl:apply-templates />
<xsl:text>](</xsl:text>
<xsl:value-of select="@href" />
<xsl:text>)</xsl:text>
<xsl:value-of select="my:addSpaceIfNeeded(.)" />
</xsl:template>

<xsl:template match="img">
<xsl:text>&#10;</xsl:text>
<xsl:text>![</xsl:text>
<xsl:value-of select="@alt" />
<xsl:text>](</xsl:text>
<xsl:value-of select="@src" />
<xsl:text>)</xsl:text>
<xsl:text>&#10;</xsl:text>
<xsl:value-of select="my:addSpaceIfNeeded(.)" />
</xsl:template>

<xsl:template match="strong|b">
<xsl:text>**</xsl:text>
<xsl:apply-templates />
<xsl:text>**</xsl:text>
<xsl:value-of select="my:addSpaceIfNeeded(.)" />
</xsl:template>

<xsl:template match="em|i">
<xsl:value-of select="my:addSpaceBeforeIfNeeded(.)" />
<xsl:text>*</xsl:text>
<xsl:value-of select="normalize-space(.)" />
<xsl:text>*</xsl:text>
<xsl:value-of select="my:addSpaceIfNeeded(.)" />
</xsl:template>

<xsl:template match="pre">
<xsl:text>&#10;&#96;&#96;&#96;&#10;</xsl:text>
<xsl:apply-templates select="node()" mode="codeblock" />
<xsl:text>&#10;&#96;&#96;&#96;&#10;</xsl:text>
</xsl:template>

<xsl:template match="code" mode="codeblock">
<xsl:apply-templates select="node()" />
</xsl:template>

<xsl:template match="code">
<xsl:text>`</xsl:text>
<xsl:apply-templates select="node()" />
<xsl:text>`</xsl:text>
<xsl:value-of select="my:addSpaceIfNeeded(.)" />
</xsl:template>

<!-- Lists -->
<xsl:template match="ul">
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates select="li" />
</xsl:template>

<xsl:template match="li">
<xsl:text>- </xsl:text>
<xsl:apply-templates />
<xsl:text>&#10;</xsl:text>
</xsl:template>
</xsl:stylesheet>
Loading