The correct way to write what you have attempted is:
<xsl:template match="/ns:Library/ns:Book/@*[name() = 'title' or name() = 'author' or name() = 'isbn' or name() = 'publisher']"/>
which is of course not really considerably shorter. But there are other ways to write code that is more concise:
1 Write separate templates for the element and attribute matches
To avoid overly long expressions you could split your code into separate templates. In a first template, match the element:
<xsl:template match="/ns:Library/ns:Book">
<xsl:copy>
<xsl:apply-templates select="@*"/>
</xsl:copy>
</xsl:template>
then, write a template for attributes:
<xsl:template match="@title|@author|@isbn|@publisher">
<!--Process attributes-->
</xsl:template>
2 Specify which attributes should not be matched
<xsl:template match="/ns:Library/ns:Book/@*[name() != 'date']"/>
Ultimately, it depends on your input XML data and the XSLT context whether any of those methods makes sense. For example, if there are, say, 100 attributes that you don't want to match, then the second idea is not helpful.
Your main focus should be first on accuracy (producing the correct output XML), second on readability of code. If changes to your XSLT code do not improve either of those, then perhaps it's a bad idea to change the stylesheet at all.