ph-schematron/src/main/java/com/helger/schematron/xpath/XQueryAsXPathFunctionConverter.java
@Nonnull
  public MapBasedXPathFunctionResolver loadXQuery (@Nonnull @WillClose final InputStream aXQueryIS) throws XPathException,
                                                                                                    IOException
  {
    ValueEnforcer.notNull (aXQueryIS, "XQueryIS");

    try
    {
      final MapBasedXPathFunctionResolver aFunctionResolver = new MapBasedXPathFunctionResolver ();

      // create a Configuration object
      final Configuration aConfiguration = new Configuration ();
      final DynamicQueryContext aDynamicQueryContext = new DynamicQueryContext (aConfiguration);
      final StaticQueryContext aStaticQueryCtx = aConfiguration.newStaticQueryContext ();
      // The base URI required for resolving within the XQuery
      aStaticQueryCtx.setBaseURI (m_sBaseURL);
      // null == auto detect
      final String sEncoding = null;
      final XQueryExpression exp = aStaticQueryCtx.compileQuery (aXQueryIS, sEncoding);
      final Controller aXQController = exp.newController (aDynamicQueryContext);

      // find all loaded methods and convert them to XPath functions
      final FunctionLibraryList aFuncLibList = exp.getExecutable ().getFunctionLibrary ();
      for (final FunctionLibrary aFuncLib : aFuncLibList.getLibraryList ())
      {
        // Ignore all Vendor, System etc. internal libraries
        if (aFuncLib instanceof FunctionLibraryList)
        {
          // This block works with Saxon HE 9.5.1-x :)
          // This is the custom function library list
          final FunctionLibraryList aRealFuncLib = (FunctionLibraryList) aFuncLib;
          for (final FunctionLibrary aNestedFuncLib : aRealFuncLib.getLibraryList ())
          {
            // Currently the user functions are in ExecutableFunctionLibrary
            if (aNestedFuncLib instanceof ExecutableFunctionLibrary)
              for (final UserFunction aUserFunc : new IterableIterator <> (((ExecutableFunctionLibrary) aNestedFuncLib).iterateFunctions ()))
              {
                // Saxon 9.7 changes "getNumberOfArguments" to "getArity"
                aFunctionResolver.addUniqueFunction (aUserFunc.getFunctionName ().getNamespaceBinding ().getURI (),
                                                     aUserFunc.getFunctionName ().getLocalPart (),
                                                     aUserFunc.getArity (),
                                                     new XPathFunctionFromUserFunction (aConfiguration,
                                                                                        aXQController,
                                                                                        aUserFunc));
              }
          }
        }
        else
          if (aFuncLib instanceof XQueryFunctionLibrary)
          {
            // This block works with Saxon HE 9.6.0-x :)
            final XQueryFunctionLibrary aRealFuncLib = (XQueryFunctionLibrary) aFuncLib;
            for (final XQueryFunction aXQueryFunction : new IterableIterator <> (aRealFuncLib.getFunctionDefinitions ()))
            {
              // Ensure the function is compiled
              aXQueryFunction.compile ();
              aFunctionResolver.addUniqueFunction (aXQueryFunction.getFunctionName ().getNamespaceBinding ().getURI (),
                                                   aXQueryFunction.getFunctionName ().getLocalPart (),
                                                   aXQueryFunction.getNumberOfArguments (),
                                                   new XPathFunctionFromUserFunction (aConfiguration,
                                                                                      aXQController,
                                                                                      aXQueryFunction.getUserFunction ()));
            }
          }
      }

      return aFunctionResolver;
    }
    finally
    {
      StreamHelper.close (aXQueryIS);
    }
  }
@Nonnull
  public MapBasedXPathFunctionResolver loadXQuery (@Nonnull @WillClose final InputStream aXQueryIS) throws XPathException,
                                                                                                    IOException
  {
    ValueEnforcer.notNull (aXQueryIS, "XQueryIS");

    try
    {
      final MapBasedXPathFunctionResolver aFunctionResolver = new MapBasedXPathFunctionResolver ();

      // create a Configuration object
      final Configuration aConfiguration = new Configuration ();
      final DynamicQueryContext aDynamicQueryContext = new DynamicQueryContext (aConfiguration);
      final StaticQueryContext aStaticQueryCtx = aConfiguration.newStaticQueryContext ();
      // The base URI required for resolving within the XQuery
      aStaticQueryCtx.setBaseURI (m_sBaseURL);
      // null == auto detect
      final String sEncoding = null;
      final XQueryExpression exp = aStaticQueryCtx.compileQuery (aXQueryIS, sEncoding);
      final Controller aXQController = exp.newController (aDynamicQueryContext);

      // find all loaded methods and convert them to XPath functions
      final FunctionLibraryList aFuncLibList = exp.getExecutable ().getFunctionLibrary ();
      for (final FunctionLibrary aFuncLib : aFuncLibList.getLibraryList ())
      {
        // Ignore all Vendor, System etc. internal libraries
        if (aFuncLib instanceof FunctionLibraryList)
        {
          // This block works with Saxon HE 9.5.1-x :)
          // This is the custom function library list
          final FunctionLibraryList aRealFuncLib = (FunctionLibraryList) aFuncLib;
          for (final FunctionLibrary aNestedFuncLib : aRealFuncLib.getLibraryList ())
          {
            // Currently the user functions are in ExecutableFunctionLibrary
            if (aNestedFuncLib instanceof ExecutableFunctionLibrary)
              for (final UserFunction aUserFunc : new IterableIterator <> (((ExecutableFunctionLibrary) aNestedFuncLib).iterateFunctions ()))
              {
                // Saxon 9.7 changes "getNumberOfArguments" to "getArity"
                aFunctionResolver.addUniqueFunction (aUserFunc.getFunctionName ().getNamespaceBinding ().getURI (),
                                                     aUserFunc.getFunctionName ().getLocalPart (),
                                                     aUserFunc.getArity (),
                                                     new XPathFunctionFromUserFunction (aConfiguration,
                                                                                        aXQController,
                                                                                        aUserFunc));
              }
          }
        }
        else
          if (aFuncLib instanceof XQueryFunctionLibrary)
          {
            // This block works with Saxon HE 9.6.0-x :)
            final XQueryFunctionLibrary aRealFuncLib = (XQueryFunctionLibrary) aFuncLib;
            for (final XQueryFunction aXQueryFunction : new IterableIterator <> (aRealFuncLib.getFunctionDefinitions ()))
            {
              // Ensure the function is compiled
              aXQueryFunction.compile ();
              aFunctionResolver.addUniqueFunction (aXQueryFunction.getFunctionName ().getNamespaceBinding ().getURI (),
                                                   aXQueryFunction.getFunctionName ().getLocalPart (),
                                                   aXQueryFunction.getNumberOfArguments (),
                                                   new XPathFunctionFromUserFunction (aConfiguration,
                                                                                      aXQController,
                                                                                      aXQueryFunction.getUserFunction ()));
            }
          }
      }

      return aFunctionResolver;
    }
    finally
    {
      StreamHelper.close (aXQueryIS);
    }
  }
Load XQuery functions from an input stream. As this function is supposed to
work with Saxon HE, this method allows only for loading full XQuery modules
and not for XQuery libraries.

@param aXQueryIS
The Input Stream to read from. May not be <code>null</code>. Will be
closed automatically in this method.
@return A non-<code>null</code> {@link MapBasedXPathFunctionResolver}
containing all loaded functions.
@throws XPathException
if the syntax of the expression is wrong, or if it references
namespaces, variables, or functions that have not been declared, or
any other static error is reported.
@throws IOException
if a failure occurs reading the supplied input.