Looking to transform an XML file to a valid DTD topic. To do this I need to insert a body element as shown.
<topic>
<title>My Title</title>
==><body>
<para>Intro text goes here.</para>
<section/>
<section/>
==></body>
</topic>
If you need to add a body
element as a child of topic
, add a template that matches topic
and add the element there.
The only slightly tricky part is that you want the title
outside of body
, so you'll have to separate that from the rest of the children.
Here's an XSLT 3.0 example. (I also added an id
attribute to topic
and changed para
to p
so it would be valid.)
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" doctype-public="-//OASIS//DTD DITA Topic//EN" doctype-system="topic.dtd"/>
<xsl:strip-space elements="*"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="topic">
<topic id="{generate-id()}">
<xsl:apply-templates select="@*|title"/>
<body>
<xsl:apply-templates select="node() except title"/>
</body>
</topic>
</xsl:template>
<xsl:template match="para">
<p>
<xsl:apply-templates select="@*|node()"/>
</p>
</xsl:template>
</xsl:stylesheet>
If you can't use XSLT 3.0, here's a 1.0 version (without xsl:mode
and except
)...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" doctype-public="-//OASIS//DTD DITA Topic//EN" doctype-system="topic.dtd"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="topic">
<topic id="{generate-id()}">
<xsl:apply-templates select="@*|title"/>
<body>
<xsl:apply-templates select="node()[not(self::title)]"/>
</body>
</topic>
</xsl:template>
<xsl:template match="para">
<p>
<xsl:apply-templates select="@*|node()"/>
</p>
</xsl:template>
</xsl:stylesheet>