XSLT 2.0でフラットな文書を構造化

怠けてる間にXSLT 2.0が当たり前になってた。

昔は大変だったのだ……

それが今は……

source.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
	<title>source</title>
  </head>
  <body>
	<p>foobar</p>
	<h1>hoge</h1>
	<p>hoge</p>
	<h2>piyo</h2>
	<p>piyo</p>
	<h3>fuga</h3>
	<p>fuga</p>
  </body>
</html>

style.xsl

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xsl:stylesheet [
  <!ENTITY xmlns 'http://www.w3.org/1999/xhtml'>
  ]>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns="&xmlns;"
  xpath-default-namespace="&xmlns;">

  <xsl:output method="xml"
	encoding="utf-8"
	omit-xml-declaration="yes"
	doctype-system="about:legacy-compat"
	indent="yes"
	media-type="application/xhtml+xml" />

  <xsl:template match="*">
	<xsl:copy>
	  <xsl:copy-of select="@*" />
	  <xsl:apply-templates />
	</xsl:copy>
  </xsl:template>

  <xsl:template match="body">
	<xsl:copy>
	  <xsl:copy-of select="@*" />
	  <xsl:for-each-group select="*" group-starting-with="h1">
		<xsl:apply-templates select="." mode="group" />
	  </xsl:for-each-group>
	</xsl:copy>
  </xsl:template>

  <xsl:template match="*" mode="group">
	<xsl:copy-of select="current-group()" />
  </xsl:template>

  <xsl:template match="h1" mode="group">
	<section>
	  <xsl:copy-of select="." />
	  <xsl:for-each-group select="current-group() except ." group-starting-with="h2">
		<xsl:apply-templates select="." mode="group" />
	  </xsl:for-each-group>
	</section>
  </xsl:template>

  <xsl:template match="h2" mode="group">
	<section>
	  <xsl:copy-of select="." />
	  <xsl:for-each-group select="current-group() except ." group-starting-with="h3">
		<xsl:apply-templates select="." mode="group" />
	  </xsl:for-each-group>
	</section>
  </xsl:template>

  <xsl:template match="h3" mode="group">
	<section>
	  <xsl:copy-of select="." />
	  <xsl:copy-of select="current-group() except ." />
	</section>
  </xsl:template>

</xsl:stylesheet>

struct.bat

@echo off
setlocal
java -jar saxon.jar source.xml style.xsl > result_saxon.html
AltovaXML.exe /xslt2 style.xsl /in source.xml /out result_altova.html
endlocal
echo on

result_saxon.html

<!DOCTYPE html
  SYSTEM "about:legacy-compat">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
	     <title>source</title>
  </head>
  <body>
      <p>foobar</p>
      <section>
         <h1>hoge</h1>
         <p>hoge</p>
         <section>
            <h2>piyo</h2>
            <p>piyo</p>
            <section>
               <h3>fuga</h3>
               <p>fuga</p>
            </section>
         </section>
      </section>
   </body>
</html>

涙が出そうになる。