Making saxon-c available in Python

Question:

I have just read that Saxon is now available for Python, and that’s just great fun and good, but can anyone write a tutorial on how to make it available for Python/Anaconda/WingIDE or similar? I am used to installing with pip or conda, and pointing to a package/wheel for integration in my environment, but I have never started from scratch, as it feels I am doing here, or am I missing something?

The doc states that:

The Python extension on the Linux and MacOS platforms can be built using the following command:python3 saxon-setup.py build_ext -if

Well, I’m on a windows machine so what then? I’ve tried to read up on this subject, but recepies and ".h" files seems to be way over my head.

I just really want to get this to work on Python, but for now, I’m stuck with xslt and xpath 1.0 in Python, and having to wrestle through Java for xslt 2+.

Any help would be apreciated!

I will write another question here on StackOverflow, but with focus on how to build using Cython when I have a 64-bit version of Anaconda installed. This seems to be my initial problem.

Asked By: Zug_Bug

||

Answers:

I have managed to build saxonc for Python on a couple of Windows 10 machines where I had already installed Visual Studio 2017 or 2019 with Python 3 support and C/C++ support.

The steps are roughly, for the current version of SaxonC HE:

  • Install SaxonC HE 11.3 from Saxonica
  • For Python: update pip
  • Use pip to install Cython: pip install Cython
  • open Powershell for e.g. Python 3.9 (with administrator rights if you installed in C:Program Files)
  • cd Saxon install dir (e.g. cd C:Program FilesSaxonicaSaxonC HE 11.3)
  • cd Saxon.C.APIpython-saxon
  • run py saxon-setup.py build_ext -if
  • for arbitrary Powershell Windows need to set SAXONC_HOME to the installation dir e.g. $env:SAXONC_HOME='C:Program FilesSaxonicaSaxonC HE 11.3' and PYTHONPATH: $Env:PYTHONPATH += ";C:Program FilesSaxonicaSaxonC HE 11.3Saxon.C.APIpython-saxon" to ensure that "import saxonc" in any Python program finds the saxonc module

For Saxon-C HE 1.2.1 they are:

  • Install Saxon-C HE 1.2.1 from Saxonica
  • For Python: update pip
  • Use pip to install Cython: pip install Cython
  • open Powershell for Python 3.7 (with administrator rights if you installed in C:Program Files)
  • cd Saxon install dir (e.g. cd C:Program FilesSaxonicaSaxonHEC1.2.1)
  • cd Saxon.C.APIpython-saxon
  • run py saxon-setup.py build_ext -if
  • for arbitrary Powershell Windows need to set: $Env:PYTHONPATH += ";C:Program FilesSaxonicaSaxonHEC1.2.1Saxon.C.APIpython-saxon" to ensure that "import saxonc" in any Python program finds the saxonc module
Answered By: Martin Honnen

[Linux Mint*] Xslt in Python

Step-by-step instructions to get you from zero to python xslt "hello world" in 10 minutes**

Installation

  1. [File Explorer] Download SaxonC-HE from the C/C++, PHP and Python downloads page.
  2. [File Explorer] Go to the "download" folder from the previous step.
  3. [File Explorer] Unzip the file from the download step.
  4. [Terminal] Go into the newly created "libsaxon" folder: cd libsaxon-HEC-11.4.
  5. [Terminal] Copy the SaxonC library: sudo cp libsaxonhec.so /usr/lib/.
  6. [Terminal] Copy the Excelsior JET runtime (which handles VM calls): sudo cp -r rt /usr/lib/.
  7. [Terminal] Copy the Saxon data folder: sudo cp -r saxon-data /usr/lib/.
  8. [Terminal] Set the SAXONC_HOME environment variable: export SAXONC_HOME=/usr/lib
  9. [Terminal] Go to the "python saxon" folder: cd Saxon.C.API/python-saxon
  10. [Terminal] Update pip: python -m pip install --upgrade pip
  11. [Terminal] Install Cython: pip install Cython
  12. [Terminal] Install python-saxon: python saxon-setup.py build_ext -if
  13. [Terminal] Set PYTHONPATH variable: export PYTHONPATH=/home/toddmo/Downloads/libsaxon-HEC-11.4/Saxon.C.API/python-saxon. Replace my username with yours.

Hello World

  1. [File Explorer] Create the following files, listed below, in a test folder
  2. [Terminal] Run Hello world: python saxon-test.py. Make sure you’re in the test folder and your PYTHONPATH env variable is set as indicated above.

saxon-test.py

import os
import saxonc

with saxonc.PySaxonProcessor(license=True) as saxonproc:
   xsltproc = saxonproc.new_xslt30_processor()
   saxonproc.set_cwd(os.getcwd())
   out = xsltproc.transform_to_string(source_file="in.xml", stylesheet_file="test.xsl")
   with open("out.xml", "w") as f:
     f.write(out)
   print(out)
   out_contents = saxonproc.parse_xml(xml_file_name="out.xml")
   print(out_contents)

test.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet ><hello>
    <world/>
</hello>

Making Paths permanent

  1. [Terminal] Start editing the bash profile: nano ~/.bash_profile
  2. [Nano] Paste the code from "Set PYTHONPATH variable" above
  3. [Nano] Save the changes: CTRL+X, Y, ENTER
  4. [Terminal] Start editing the bash profile: nano ~/.bash_profile
  5. [Nano] Paste the code from "Set PYTHONPATH variable" above, but it should look like this instead: export PYTHONPATH="${PYTHONPATH}:/my/other/path". Note the $ sign and curly braces.
  6. [Nano] Save the changes: CTRL+X, Y, ENTER
  7. [Terminal] Run source: source ~/.bashrc
  8. [Desktop] Open a new Terminal
  9. [Terminal] Test it: echo $PYTHONPATH

Getting all this going in Visual Studio Code

  1. [VS Code] [Terminal] The PYTHONPATH variable should be populated in here: echo $PYTHONPATH
  2. [VS Code] [Terminal] Hello World should work in here: python saxon-test.py
  3. [VS Code] [Extensions] Install Python
  4. [VS Code] [Extensions] Install Pylance
  5. [VS Code] [Extensions] Install XSL Transform. It allows you to do transformations with CTRL+SHIFT+P
  6. [VS Code] [Extensions] Install XSLT/XPath for Visual Studio Code
  7. [VS Code] Copy saxon-test.py into a VS Code project
  8. [VS Code] Rename it to xslt.py
  9. [VS Code] [xslt.py] Replace the contents to what is listed below
  10. [VS Code] You may notice saxonc has a red line, with the mouse hover message: Import "saxonc" could not be resolved Pylance (reportMissingImports)
  11. If you try to call the function, you may get the runtime error: ModuleNotFoundError: No module named 'saxonc'
  12. [VS Code] [Run and Debug Sidebar] Add launch.json.
  13. [VS Code] [launch.json] Add configurations for a Python file, Django, and / or whatever you need.
  14. [VS Code] [launch.json] Add the env variable to all of your configurations(s): "env": {"PYTHONPATH":${workspaceFolder}${pathSeparator}${env:PYTHONPATH}"}
  15. [Desktop] Restart VS Code.
  16. [VS Code] [xslt.py] import saxonc should now be working with no error.

xslt.py

import os
import saxonc

from typing import Dict

class Xslt():

  @classmethod
  def transform(cls, xsl_file: str, xml_file: str, output_file: str, parameters: Dict[str,str]) -> bool:
    try:
      out = cls.transform_to_string(xsl_file, xml_file, parameters)
      with open(output_file, "w") as f:
        f.write(out)
      return True
    except Exception as e:
      print(str(e))
      return False

  @classmethod
  def transform_to_string(cls, xsl_file: str, xml_file: str, parameters: Dict[str,str]) -> str:
    with saxonc.PySaxonProcessor(license=True) as saxonproc:
      xsltproc = saxonproc.new_xslt30_processor()
      for parameter in parameters:
        xsltproc.set_parameter(parameter, saxonproc.make_string_value(parameters[parameter]))
      saxonproc.set_cwd(os.getcwd())
      return xsltproc.transform_to_string(source_file=xml_file, stylesheet_file=xsl_file)

  
  def parse_xml(self, xml_file):
    with saxonc.PySaxonProcessor(license=True) as saxonproc:
      return saxonproc.parse_xml(xml_file_name=xml_file)

* This will probably work on any Ubuntu system.

** I had to cobble these together from multiple locations. Some of the instructions are here. I point this out because I was unable to find this "Getting started" from the home page, the download page, or any other pages quoted. I stumbled upon it in another S/O question. To do all these instructions took hours.

Answered By: toddmo
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.