← all checks
warning suggested fix checked over the tokens, not an XPath rule

--fix-suggestions rewrites this one, and a plain --fix leaves it alone: the correction changes what the stylesheet does, or is one of several the check would accept.

Redundant import

Referencing the same module twice the same way in one stylesheet adds nothing — both references bring in the same templates, functions, and variables. At best it is noise; at worst it hides which reference a reader should reason about. Keep a single reference per module.

A repeated xsl:import is not simply noise, though, and removing one is not simply tidying. Import precedence is positional — XSLT 1.0 §2.6.2 ranks each xsl:import above everything declared before it — so importing one module twice puts that module at two precedence levels at once, and both of them are live. Two things follow, and they pull in opposite directions.

The later reference is the one that decides which module wins. With another module imported in between, the two references sit on opposite sides of it, so alpha below overrides beta, and it would not if the third line were the one removed:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="alpha.xsl"/>
  <xsl:import href="beta.xsl"/>
  <xsl:import href="alpha.xsl"/>
</xsl:stylesheet>

The earlier reference is not idle either, because xsl:apply-imports walks down the precedence chain and meets the module at every level it occupies. Where alpha.xsl ends its rule in an xsl:apply-imports, that stylesheet emits ABAalpha at the top level, then beta, then alpha again at the bottom one. Import it twice with nothing in between and the output is AA where a single import gives A. XSLT 2.0's xsl:next-match walks the same chain.

So a duplicate xsl:import is a decision to make by hand, with the whole stylesheet's overriding in view. Where the module's rules do not reach back down the chain, one reference is enough:

Incorrect:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="alpha.xsl"/>
  <xsl:import href="beta.xsl"/>
  <xsl:import href="alpha.xsl"/>
</xsl:stylesheet>

Correct:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="beta.xsl"/>
  <xsl:import href="alpha.xsl"/>
</xsl:stylesheet>

A repeated xsl:include is not exempt, though it looks it. An include creates no precedence level of its own — the module's definitions land at the level of the stylesheet including it — but it copies that module's children in, and those children include its own xsl:import elements. Include a module twice and its imports arrive twice, at two levels, and the same traversal walks both. Where gamma.xsl imports delta.xsl, this emits GDD, and GD with one of the includes removed:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:include href="gamma.xsl"/>
  <xsl:include href="gamma.xsl"/>
</xsl:stylesheet>

Only where the included module imports nothing, directly or through what it includes, is the repeat pure noise.

The linter resolves each @href against the importing file's own directory, so two spellings that point at the same file (lib/util.xsl and ./lib/util.xsl) count as one, and a module imported once directly and once from a sibling is not confused with a genuine duplicate — only repeats within a single stylesheet's own list are flagged. A self-import or a cross-file cycle is a different fault, reported by circular-import. A reference carrying no @href names no module at all, and is invalid XSLT rather than a duplicate.

Incorrect:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="common.xsl"/>
  <xsl:import href="common.xsl"/>
</xsl:stylesheet>

Correct:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="common.xsl"/>
</xsl:stylesheet>

Reaching one module both ways is worse than noise, because the two mechanisms do not agree on precedence. xsl:include places the module's definitions at the precedence of the including stylesheet's own, while xsl:import places them below it. So importing and also including one module gives every definition in it two lives at two levels: the imported copy is shadowed by the included one, and a template the stylesheet defines for itself now collides with the included copy at equal precedence instead of quietly overriding the imported one.

Which reference to drop is therefore a decision about precedence, not a tidying up. Keep the xsl:include to let the module's definitions rank alongside the stylesheet's own, or keep the xsl:import to let the stylesheet's own override them — then delete the other.

Incorrect:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="common.xsl"/>
  <xsl:include href="common.xsl"/>
</xsl:stylesheet>

Correct:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:include href="common.xsl"/>
</xsl:stylesheet>