code: @Nonnull
    public PSPhase readPhaseFromXML (@Nonnull final IMicroElement ePhase)
    {
      final PSPhase ret = new PSPhase ();
  
      final PSRichGroup aRichGroup = new PSRichGroup ();
      ePhase.forAllAttributes ( (sNS, sAttrName, sVal) -> {
        final String sAttrValue = _getAttributeValue (sVal);
        if (sAttrName.equals (CSchematronXML.ATTR_ID))
          ret.setID (sAttrValue);
        else
          if (PSRichGroup.isRichAttribute (sAttrName))
            _handleRichGroup (sAttrName, sAttrValue, aRichGroup);
          else
            ret.addForeignAttribute (sAttrName, sAttrValue);
      });
      ret.setRich (aRichGroup);
  
      ePhase.forAllChildElements (ePhaseChild -> {
        if (CSchematron.NAMESPACE_SCHEMATRON.equals (ePhaseChild.getNamespaceURI ()))
        {
          if (ePhaseChild.getLocalName ().equals (CSchematronXML.ELEMENT_INCLUDE))
            ret.addInclude (readIncludeFromXML (ePhaseChild));
          else
            if (ePhaseChild.getLocalName ().equals (CSchematronXML.ELEMENT_P))
              ret.addP (readPFromXML (ePhaseChild));
            else
              if (ePhaseChild.getLocalName ().equals (CSchematronXML.ELEMENT_LET))
                ret.addLet (readLetFromXML (ePhaseChild));
              else
                if (ePhaseChild.getLocalName ().equals (CSchematronXML.ELEMENT_ACTIVE))
                  ret.addActive (readActiveFromXML (ePhaseChild));
                else
                  _warn (ret, "Unsupported Schematron element '" + ePhaseChild.getLocalName () + "'");
        }
        else
          ret.addForeignElement (ePhaseChild.getClone ());
      });
      return ret;
    }
docs: Read a &lt;phase&gt; element
  
  @param ePhase
  The source micro element. Never <code>null</code>.
  @return The created domain object. May not be <code>null</code>.