You have pretty much described what XSLT does (assuming the "template" is unchanging). You just need to rewrite the template as an XSLT stylesheet, for example like this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<Request>
<Inputs>
<xsl:copy-of select="ClientData/Inputs/Client"/>
<RuleCategories>
<RuleCategory>
<Name>Basic Rules</Name>
<Rules>
<Rule>
<Name>Standard Basic Rule 1</Name>
<Logic>if foo then bar</Logic>
</Rule>
<Rule>
<Name>Standard Basic Rule 2</Name>
<Logic>if bar then foo</Logic>
</Rule>
<xsl:copy-of select="ClientData/Inputs/RuleCategories/RuleCategory[Name='Basic Rules']/Rules/Rule"/>
</Rules>
</RuleCategory>
<RuleCategory>
<Name>Intermediate Rules</Name>
<Rules>
<Rule>
<Name>Standard Intermediate Rule 1</Name>
<Logic>if fooz then barz</Logic>
</Rule>
<Rule>
<Name>Standard Intermediate Rule 2</Name>
<Logic>if barz then fooz</Logic>
</Rule>
<xsl:copy-of select="ClientData/Inputs/RuleCategories/RuleCategory[Name='Intermediate Rules']/Rules/Rule"/>
</Rules>
</RuleCategory>
</RuleCategories>
</Inputs>
<Outputs>
<Queries>
<Query>
<Name>All the foos</Name>
<Logic>Select all foos</Logic>
</Query>
<Query>
<Name>All the bars</Name>
<Logic>Select all the bars</Logic>
</Query>
<xsl:copy-of select="ClientData/Outputs/Queries/Query"/>
</Queries>
</Outputs>
</Request>
</xsl:template>
</xsl:stylesheet>
Note that the result of the transformation is not much different from the source client data document - so the more experienced programmer would likely start by copying everything as is using the identity transform template, then add a few more templates to handle the exceptions e.g.:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- exceptions -->
<xsl:template match="/ClientData">
<Request>
<xsl:apply-templates select="@*|node()"/>
</Request>
</xsl:template>
<xsl:template match="Queries">
<xsl:copy>
<Query>
<Name>All the foos</Name>
<Logic>Select all foos</Logic>
</Query>
<Query>
<Name>All the bars</Name>
<Logic>Select all the bars</Logic>
</Query>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
This needs more work to handle boiler-plate category rules in a manner similar to the boiler-plate queries.