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.
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
[Linux Mint*] Xslt in Python
Step-by-step instructions to get you from zero to python xslt "hello world" in 10 minutes**
Installation
- [File Explorer] Download SaxonC-HE from the C/C++, PHP and Python downloads page.
- [File Explorer] Go to the "download" folder from the previous step.
- [File Explorer] Unzip the file from the download step.
- [Terminal] Go into the newly created "libsaxon" folder:
cd libsaxon-HEC-11.4
.
- [Terminal] Copy the SaxonC library:
sudo cp libsaxonhec.so /usr/lib/.
- [Terminal] Copy the Excelsior JET runtime (which handles VM calls):
sudo cp -r rt /usr/lib/.
- [Terminal] Copy the Saxon data folder:
sudo cp -r saxon-data /usr/lib/.
- [Terminal] Set the SAXONC_HOME environment variable:
export SAXONC_HOME=/usr/lib
- [Terminal] Go to the "python saxon" folder:
cd Saxon.C.API/python-saxon
- [Terminal] Update pip:
python -m pip install --upgrade pip
- [Terminal] Install Cython:
pip install Cython
- [Terminal] Install python-saxon:
python saxon-setup.py build_ext -if
- [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
- [File Explorer] Create the following files, listed below, in a test folder
- [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
- [Terminal] Start editing the bash profile:
nano ~/.bash_profile
- [Nano] Paste the code from "Set PYTHONPATH variable" above
- [Nano] Save the changes: CTRL+X, Y, ENTER
- [Terminal] Start editing the bash profile:
nano ~/.bash_profile
- [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.
- [Nano] Save the changes: CTRL+X, Y, ENTER
- [Terminal] Run source:
source ~/.bashrc
- [Desktop] Open a new Terminal
- [Terminal] Test it:
echo $PYTHONPATH
Getting all this going in Visual Studio Code
- [VS Code] [Terminal] The PYTHONPATH variable should be populated in here:
echo $PYTHONPATH
- [VS Code] [Terminal] Hello World should work in here:
python saxon-test.py
- [VS Code] [Extensions] Install
Python
- [VS Code] [Extensions] Install
Pylance
- [VS Code] [Extensions] Install
XSL Transform
. It allows you to do transformations with CTRL+SHIFT+P
- [VS Code] [Extensions] Install
XSLT/XPath for Visual Studio Code
- [VS Code] Copy
saxon-test.py
into a VS Code project
- [VS Code] Rename it to
xslt.py
- [VS Code] [xslt.py] Replace the contents to what is listed below
- [VS Code] You may notice
saxonc
has a red line, with the mouse hover message: Import "saxonc" could not be resolved Pylance (reportMissingImports)
- If you try to call the function, you may get the runtime error:
ModuleNotFoundError: No module named 'saxonc'
- [VS Code] [Run and Debug Sidebar] Add
launch.json
.
- [VS Code] [launch.json] Add configurations for a Python file, Django, and / or whatever you need.
- [VS Code] [launch.json] Add the
env
variable to all of your configurations(s): "env": {"PYTHONPATH":${workspaceFolder}${pathSeparator}${env:PYTHONPATH}"}
- [Desktop] Restart VS Code.
- [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.
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.
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'
andPYTHONPATH
:$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
[Linux Mint*] Xslt in Python
Step-by-step instructions to get you from zero to python xslt "hello world" in 10 minutes**
Installation
- [File Explorer] Download SaxonC-HE from the C/C++, PHP and Python downloads page.
- [File Explorer] Go to the "download" folder from the previous step.
- [File Explorer] Unzip the file from the download step.
- [Terminal] Go into the newly created "libsaxon" folder:
cd libsaxon-HEC-11.4
. - [Terminal] Copy the SaxonC library:
sudo cp libsaxonhec.so /usr/lib/.
- [Terminal] Copy the Excelsior JET runtime (which handles VM calls):
sudo cp -r rt /usr/lib/.
- [Terminal] Copy the Saxon data folder:
sudo cp -r saxon-data /usr/lib/.
- [Terminal] Set the SAXONC_HOME environment variable:
export SAXONC_HOME=/usr/lib
- [Terminal] Go to the "python saxon" folder:
cd Saxon.C.API/python-saxon
- [Terminal] Update pip:
python -m pip install --upgrade pip
- [Terminal] Install Cython:
pip install Cython
- [Terminal] Install python-saxon:
python saxon-setup.py build_ext -if
- [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
- [File Explorer] Create the following files, listed below, in a test folder
- [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
- [Terminal] Start editing the bash profile:
nano ~/.bash_profile
- [Nano] Paste the code from "Set PYTHONPATH variable" above
- [Nano] Save the changes: CTRL+X, Y, ENTER
- [Terminal] Start editing the bash profile:
nano ~/.bash_profile
- [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. - [Nano] Save the changes: CTRL+X, Y, ENTER
- [Terminal] Run source:
source ~/.bashrc
- [Desktop] Open a new Terminal
- [Terminal] Test it:
echo $PYTHONPATH
Getting all this going in Visual Studio Code
- [VS Code] [Terminal] The PYTHONPATH variable should be populated in here:
echo $PYTHONPATH
- [VS Code] [Terminal] Hello World should work in here:
python saxon-test.py
- [VS Code] [Extensions] Install
Python
- [VS Code] [Extensions] Install
Pylance
- [VS Code] [Extensions] Install
XSL Transform
. It allows you to do transformations with CTRL+SHIFT+P - [VS Code] [Extensions] Install
XSLT/XPath for Visual Studio Code
- [VS Code] Copy
saxon-test.py
into a VS Code project - [VS Code] Rename it to
xslt.py
- [VS Code] [xslt.py] Replace the contents to what is listed below
- [VS Code] You may notice
saxonc
has a red line, with the mouse hover message:Import "saxonc" could not be resolved Pylance (reportMissingImports)
- If you try to call the function, you may get the runtime error:
ModuleNotFoundError: No module named 'saxonc'
- [VS Code] [Run and Debug Sidebar] Add
launch.json
. - [VS Code] [launch.json] Add configurations for a Python file, Django, and / or whatever you need.
- [VS Code] [launch.json] Add the
env
variable to all of your configurations(s):"env": {"PYTHONPATH":${workspaceFolder}${pathSeparator}${env:PYTHONPATH}"}
- [Desktop] Restart VS Code.
- [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.