##### Overview

- Download PMD 5.0.4
- What's new in PMD 5.0.4
- PMD in the news
- PMD-related products and books
- Best practices
- Future directions
- Similar projects
- Credits
- License
- What does 'PMD' mean?

##### Usage

- Installation
- Command line usage
- Ant task usage
- Maven plugin usage
- Mvn plugin usage
- IDE plugin usage
- Suppressing warnings
- Finding duplicated code
- JSP support

##### Customizing PMD

- Compiling PMD
- How to write a rule
- Writing XPath rules
- How to make a rule set
- How it works
- Rule guidelines
- PMD developers information
- PMD Release Process

##### For example

- Run PMD on a Sourceforge project

##### Misc.

- XPath tutorial (Gregorian)

##### Rule Sets

- ecmascript
  - Basic Ecmascript
  - Braces
  - Unnecessary
- java
  - Android
  - Basic
  - Braces
  - Clone Implementation
  - Code Size
  - Comments
  - Controversial
  - Coupling
  - Design
  - Empty Code
  - Finalizer
  - Import Statements
  - J2EE
  - JavaBeans
  - JUnit
  - Jakarta Commons Logging
  - Java Logging
  - Migration
  - Naming
  - Optimization
  - Strict Exceptions
  - String and StringBuffer
  - Security Code Guidelines
  - Type Resolution
  - Unnecessary
  - Unused Code
- jsp
  - Basic JSF
  - Basic JSP
- xml
  - Basic XML
- xsl
  - XPath in XSL

##### Project Documentation

- Project Information
- Project Reports

## XPath in XSL

This ruleset regroups a collection of good practices regarding XPath querying and functions inside an XSL.

### UseConcatOnce

Since: PMD 5.0

The XPath concat() functions accepts as many arguments as required so you can have "concat($a,'b',$c)" rather than "concat($a,concat('b',$c)".

    //node()[contains(substring-after(@select,'concat'),'concat')]

Example(s):

     <xsl:variable name="var" select="concat("Welcome",concat("to you ",$name))"/>
     <xsl:variable name="var" select="concat("Welcome","to you ",$name))">

### AvoidAxisNavigation

Since: PMD 5.0

Avoid using the 'following' or 'preceeding' axes whenever possible, as these can cut through 100% of the document in the worst case. Also, try to avoid using 'descendant' or 'descendant-self' axes, as if you're at the top of the Document, it necessarily means cutting through 100% of the document.

    //node()[
      contains(@select,'preceeding::')
      or
      contains(@select,'following::')
      or
      contains(@select,'descendant::')
      or
      contains(@select,'descendant-self::')
      or (
        ($checkSelfDescendantAbreviation = 'true' )
        and
        contains(@select,'//')
        )
    ]

Example(s):

     <xsl:variable name="var" select="//item/descendant::child"/>

This rule has the following properties:

Name | Default Value | Description
--- | --- | ---
checkSelfDescendantAbreviation | false | descendant::self abreviation, '//', will also trigger this rule.