Issue
I'm getting the XPDY0002 context item is absent error. I've seen the other questions regarding this but I don't really understand the answers nor do I see how to apply them to my python code.
The problem seems to occur in this strange xslt 1.0 setup where I have a node-set, identity transform and regular match="/" present. My example is a distilled version of a much more complex stylesheet that I didn't write. But the point is that it transforms with Oxygen running Saxon-HE 9.9.1.7, but with my python saxonc I get an error.
I've tried set_global_context_item() but it just hangs.
My error in pycharm
Error at char 0 in expression in xsl:for-each/@select on line 19 column 55 of stylesheet.xsl:
XPDY0002 The context item for axis step $sortedInput_nodeset/country is absent
In template rule with match="/" on line 18 of stylesheet.xsl
My python code
import os
from saxonpy import PySaxonProcessor
def main():
proc = PySaxonProcessor(license=False)
proc.set_cwd(os.getcwd())
xsltproc = proc.new_xslt30_processor()
xslt30_transformer = xsltproc.compile_stylesheet(stylesheet_file="stylesheet.xsl")
xslt30_transformer.apply_templates_returning_file(source_file="raw.xml",
output_file="result.xml")
if __name__ == "__main__":
main()
The problem still occurs when transforming from xdm_node to file:
xslt30_transformer.set_initial_match_selection(xdm_value=xml_doc)
xslt30_transformer.apply_templates_returning_file(xdm_node=xml_doc,
output_file=path_to_output_file)
My xslt stylesheet
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:exsl="http://exslt.org/common">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:variable name="sortedInput_RTF">
<xsl:apply-templates select="/data/country">
<xsl:sort select="@name" order="descending"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:variable name="sortedInput_nodeset" select="exsl:node-set($sortedInput_RTF)"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:for-each select="$sortedInput_nodeset/country">
<xsl:value-of select="@capital"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
My source xml
<?xml version="1.0" encoding="UTF-8"?>
<data>
<country name="Denmark" capital="Copenhagen"/>
<country name="Germany" capital="Berlin"/>
<country name="France" capital="Paris"/>
</data>
My output in using Saxon-HE 9.9.1.7 in Oxygen
BerlinParisCopenhagen
Follow-up
This stylesheet works (proving the problem is not exsl):
<xsl:template match="/">
<xsl:variable name="sortedInput_RTF">
<root>
<country capital="a"/>
<country capital="b"/>
<country capital="c"/>
</root>
</xsl:variable>
<xsl:variable name="sortedInput_nodeset" select="exsl:node-set($sortedInput_RTF)"/>
<xsl:for-each select="$sortedInput_nodeset/root/country">
<xsl:value-of select="@capital"/>
</xsl:for-each>
</xsl:template>
Solution
Although this stylesheet says version="1.0", you are running it with an XSLT 3.0 processor, so the 3.0 rules apply.
In 3.0, there's a distinction between the "initial match selection" (the node(s) that determine which template rule fires first), and the "global context item" (the context item for evaluating global variables). I think the failure is because the global context item is absent.
You say "I've tried set_global_context_item() but it just hangs". Well, you're doing the right thing and it shouldn't hang, so you need to follow that path and find out what's going wrong.
Note that the "transform_to_XXX" methods combine the functions of setting the global context item, setting the initial match selection, and invoking the transformation using "apply_templates".
Answered By - Michael Kay
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.