ph-schematron/src/main/java/com/helger/schematron/pure/preprocess/PSPreprocessor.java
private void _resolveRuleContent (@Nonnull final ICommonsList <IPSElement> aRuleContent,
                                    @Nonnull final PreprocessorLookup aLookup,
                                    @Nonnull final PreprocessorIDPool aIDPool,
                                    @Nullable final ICommonsMap <String, String> aParamValueMap,
                                    @Nonnull final PSRule aTargetRule) throws SchematronPreprocessException
  {
    for (final IPSElement aElement : aRuleContent)
    {
      if (aElement instanceof PSAssertReport)
      {
        final PSAssertReport aAssertReport = (PSAssertReport) aElement;
        aTargetRule.addAssertReport (_getPreprocessedAssert (aAssertReport, aIDPool, aParamValueMap));
      }
      else
      {
        final PSExtends aExtends = (PSExtends) aElement;
        final String sRuleID = aExtends.getRule ();
        final PSRule aBaseRule = aLookup.getAbstractRuleOfID (sRuleID);
        if (aBaseRule == null)
          throw new SchematronPreprocessException ("Failed to resolve rule ID '" +
                                                   sRuleID +
                                                   "' in extends statement. Available rules are: " +
                                                   aLookup.getAllAbstractRuleIDs ());

        // Recursively resolve the extends of the base rule
        _resolveRuleContent (aBaseRule.getAllContentElements (), aLookup, aIDPool, aParamValueMap, aTargetRule);

        // Copy all lets
        for (final PSLet aBaseLet : aBaseRule.getAllLets ())
          aTargetRule.addLet (aBaseLet.getClone ());
      }
    }
  }
private void _resolveRuleContent (@Nonnull final ICommonsList <IPSElement> aRuleContent,
                                    @Nonnull final PreprocessorLookup aLookup,
                                    @Nonnull final PreprocessorIDPool aIDPool,
                                    @Nullable final ICommonsMap <String, String> aParamValueMap,
                                    @Nonnull final PSRule aTargetRule) throws SchematronPreprocessException
  {
    for (final IPSElement aElement : aRuleContent)
    {
      if (aElement instanceof PSAssertReport)
      {
        final PSAssertReport aAssertReport = (PSAssertReport) aElement;
        aTargetRule.addAssertReport (_getPreprocessedAssert (aAssertReport, aIDPool, aParamValueMap));
      }
      else
      {
        final PSExtends aExtends = (PSExtends) aElement;
        final String sRuleID = aExtends.getRule ();
        final PSRule aBaseRule = aLookup.getAbstractRuleOfID (sRuleID);
        if (aBaseRule == null)
          throw new SchematronPreprocessException ("Failed to resolve rule ID '" +
                                                   sRuleID +
                                                   "' in extends statement. Available rules are: " +
                                                   aLookup.getAllAbstractRuleIDs ());

        // Recursively resolve the extends of the base rule
        _resolveRuleContent (aBaseRule.getAllContentElements (), aLookup, aIDPool, aParamValueMap, aTargetRule);

        // Copy all lets
        for (final PSLet aBaseLet : aBaseRule.getAllLets ())
          aTargetRule.addLet (aBaseLet.getClone ());
      }
    }
  }
Resolve all &lt;extends&gt; elements. This method calls itself recursively
until all extends elements are resolved.

@param aRuleContent
A list consisting of {@link PSAssertReport} and {@link PSExtends}
objects. Never <code>null</code>.
@param aLookup
The rule lookup object
@throws SchematronPreprocessException
If the base rule of an extends object could not be resolved.