Making saxon-c available in Python
Asked Answered
B

2

7

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.

Brigand answered 26/11, 2019 at 21:42 Comment(3)
Please feel free to talk directly to Saxonica about this. It's early days for the product, and there are so many configurations possible that we need to learn alongside our users. I suggest you raise it on the help forum at saxonica.plan.io, which is a more suitable place for discussions than StackOverflow, which likes to focus on straightforward questions and answers.Has
Thank you Michael for a fast response, and I will use the Saxonica forum if I can't build this, but I'm a bit out of my league here when it comes to building packages. I have installed wheels, but I've never needed to build anything first.Brigand
Things are a lot smoother now with pypi.org/project/saxonche.Mantissa
A
9

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 Files\Saxonica\SaxonC HE 11.3)
  • cd Saxon.C.API\python-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 Files\Saxonica\SaxonC HE 11.3' and PYTHONPATH: $Env:PYTHONPATH += ";C:\Program Files\Saxonica\SaxonC HE 11.3\Saxon.C.API\python-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 Files\Saxonica\SaxonHEC1.2.1)
  • cd Saxon.C.API\python-saxon
  • run py saxon-setup.py build_ext -if
  • for arbitrary Powershell Windows need to set: $Env:PYTHONPATH += ";C:\Program Files\Saxonica\SaxonHEC1.2.1\Saxon.C.API\python-saxon" to ensure that "import saxonc" in any Python program finds the saxonc module
Arteriosclerosis answered 27/11, 2019 at 14:44 Comment(5)
Thank you!! This will be so much fun to explore!Brigand
Thanks Martin. I have updated the Saxon/C documentation page: saxonica.com/saxon-c/documentation/index.html#!starting/…Kersten
When using Anaconda, this setup process is a bit messy. It might be dependent on how Anaconda was installed, but everytime I go through this, something doesn't work. If the Anaconda is installed for current user, the admin privileged Powershell doesn't find Cython. Also, setting the Path doesn't take, so I have to set this in Spyder.Brigand
ALso, if you try installing in the Program Files dir, and then due to privileges and other problems, have to uninstall and use another dir, then you will probably get an error saying that "Unable to load C:\Program Files\Saxonica\SaxonHEC1.2.1\libsaxonhec.dll". So then you'll have to install Saxon there as well. Stable.Brigand
in my case i had multiple python installations. executing the following one did the trich while installing the Cython. py -m pip install CythonIncarcerate
T
1

[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 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:array="http://www.w3.org/2005/xpath-functions/array"
                xmlns:map="http://www.w3.org/2005/xpath-functions/map"
                xmlns:math="http://www.w3.org/2005/xpath-functions/math"
                exclude-result-prefixes="#all"
                expand-text="yes"
                version="3.0">

    <xsl:output method="xml" indent="yes"/>
    <xsl:mode on-no-match="shallow-copy"/>

    <xsl:template match="/*" mode="#all">
        <xsl:copy>
            <xsl:apply-templates select="@*, node()" mode="#current"/>
        </xsl:copy>
    </xsl:template>

    

</xsl:stylesheet>

in.xml

<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.

Tania answered 10/10, 2022 at 15:39 Comment(4)
@ond1, despite all the effort that has gone into documentation, which I applaud, this process took me 2.5 hours and was quite painful. Please see if you can make "Getting Started" visible from the home page and / or the download page, and see if you can make any more of the install and getting started steps explicit, as in my answer here. Thanks!Tania
Hi @Tania What you have written is comprehensive. Thank you. I will add some notes to the Saxonc documentation. For the SaxonC 12.1 we are working on pypi package which will make things so much easier.Kersten
@ond1, niiice! Thank you very much. I appreciate all your hard work. djangoproject.com might be an extreme example, but their home page onramps new people very easily due to easy access to "getting started".Tania
Installing Saxon is easier now when pypi.org/project/saxonche is available (and also pypi.org/project/saxoncpe and pypi.org/project/saxoncee).Mantissa

© 2022 - 2024 — McMap. All rights reserved.