SaxonJS transform with nested stylesheets causes XError:Failed URI resolution - reactjs

I am trying to transform XML using stylesheets that reference other xsl stylesheets. I compile the main stylesheet using xslt3 on the command line into a .sef.json file, but when I use that .sef.json with .transform(), I get a Failed URI resolution error.
I call transform as follows:
SaxonJS.transform({
stylesheetInternal: splXslJS,
sourceText: input,
destination: 'serialized'
}, "async")
fhirXslJS is compiled from this XSL:
<?xml version="1.0" encoding="us-ascii"?>
<!--
The contents of this file are subject to the Health Level-7 Public
License Version 1.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of the
License at http://www.hl7.org/HPL/hpl.txt.
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and
limitations under the License.
The Original Code is all this file.
The Initial Developer of the Original Code is Gunther Schadow.
Portions created by Initial Developer are Copyright (C) 2002-2004
Health Level Seven, Inc. All Rights Reserved.
Contributor(s): Steven Gitterman, Brian Keller
Revision: $Id: spl.xsl,v 1.52 2005/08/26 05:59:26 gschadow Exp $
Revision: $Id: spl-common.xsl,v 2.0 2006/08/18 04:11:00 sbsuggs Exp $
-->
<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:v3="urn:hl7-org:v3" exclude-result-prefixes="v3 xsl">
<xsl:import href="./spl-common.xsl"/>
<!-- Where to find JavaScript resources -->
<xsl:param name="resourcesdir">http://www.accessdata.fda.gov/spl/stylesheet/</xsl:param>
<!-- Whether to show the clickable XML, set to "/.." instead of "1" to turn off -->
<xsl:param name="show-subjects-xml" select="/.."/>
<!-- Whether to show the data elements in special tables etc., set to "/.." instead of "1" to turn off -->
<xsl:param name="show-data" select="1"/>
<!-- This is the CSS link put into the output -->
<xsl:param name="css">http://www.accessdata.fda.gov/spl/stylesheet/spl.css</xsl:param>
<!-- Whether to show section numbers, set to 1 to enable and "/.." to turn off-->
<xsl:param name="show-section-numbers" select="/.."/>
<!-- Whether to process mixins -->
<xsl:param name="process-mixins" select="true()"/>
<xsl:param name="core-base-url">http://www.accessdata.fda.gov/spl/core</xsl:param>
<xsl:output method="html" version="5.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
</xsl:transform>
The line causing the error is this <xsl:param name="indexingDocumentTypes" select="document('indexing-doc-types.xml')/*"/> in referenced spl-common.xsl:
<?xml version="1.0" encoding="us-ascii"?>
<!--
The contents of this file are subject to the Health Level-7 Public
License Version 1.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of the
License at http://www.hl7.org/HPL/hpl.txt.
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and
limitations under the License.
The Original Code is all this file.
The Initial Developer of the Original Code is Gunther Schadow.
Portions created by Initial Developer are Copyright (C) 2002-2013
Health Level Seven, Inc. All Rights Reserved.
Contributor(s): Steven Gitterman, Brian Keller, Brian Suggs
TODO: footnote styleCode Footnote, Endnote not yet obeyed
TODO: Implementation guide needs to define linkHtml styleCodes.
-->
<xsl:transform version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:v3="urn:hl7-org:v3"
xmlns:v="http://validator.pragmaticdata.com/result"
xmlns:str="http://exslt.org/strings"
xmlns:exsl="http://exslt.org/common"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="exsl msxsl v3 xsl xsi str v">
<xsl:import href="xml-verbatim.xsl"/>
<xsl:import href="mixin.xsl"/>
<xsl:import href="substance.xsl"/>
<xsl:import href="pesticide.xsl"/>
<xsl:param name="show-subjects-xml" select="1"/>
<xsl:param name="show-data" select="/.."/>
<xsl:param name="show-section-numbers" select="/.."/>
<xsl:param name="update-check-url-base" select="/.."/>
<xsl:param name="standardSections" select="document('plr-sections.xml')/*"/>
<xsl:param name="itemCodeSystems" select="document('item-code-systems.xml')/*"/>
<xsl:param name="disclaimers" select="document('disclaimers.xml')/*"/>
<xsl:param name="documentTypes" select="document('doc-types.xml')/*"/>
<xsl:param name="indexingDocumentTypes" select="document('indexing-doc-types.xml')/*"/>
<xsl:param name="root" select="/"/>
<xsl:param name="css" select="'./spl.css'"/>
<xsl:param name="process-mixins" select="/.."/>
<xsl:output method="html" version="5.0" encoding="UTF-8" indent="no" doctype-public="-"/>
<xsl:strip-space elements="*"/>
<!-- The indication secction variable contains the actual Indication Section node-->
<xsl:variable name="indicationSection" select="/v3:document/v3:component/v3:structuredBody/v3:component//v3:section [v3:code [descendant-or-self::* [(self::v3:code or self::v3:translation) and #codeSystem='2.16.840.1.113883.6.1' and #code='34067-9'] ] ]"/>
<xsl:variable name="indicationSectionCode">34067-9</xsl:variable>
<xsl:variable name="dosageAndAdministrationSectionCode">34068-7</xsl:variable>
<xsl:variable name="timeUnitsList">
<unitsMapping>
<unit UCUM="s" singular="second" plural="seconds"/>
<unit UCUM="min" singular="minute" plural="minutes"/>
<unit UCUM="h" singular="hour" plural="hours"/>
<unit UCUM="d" singular="day" plural="days"/>
<unit UCUM="wk" singular="week" plural="weeks"/>
<unit UCUM="mo" singular="month" plural="months"/>
<unit UCUM="a" singular="year" plural="years"/>
</unitsMapping>
</xsl:variable>
(much more in this file but don't think it's necessary)
This is the error I'm getting: XError:Failed URI resolution: href=./indexing-doc-types.xml base=file:///C:/Users/7J2197897/Desktop/FDA/SPL-FHIR-Demo/spl-fhir-demo/src/assets/HTML-View-Xform-SPL/spl-common.xsl -- TypeError: r is not a constructor; code:FODC0005
Other potentially relevant context:
This is from a React app running on Firefox
Node module "saxon-js": "^2.4.0",
Compiled spl.xsl with xslt3 -xsl:spl.xsl -export:spl.sef.json --t --nogo --ns:##html5
sourceText is an XML string the user inputs
I have also tried compiling with relocate:on and passing stylesheetBaseURI but that didn't work
Appreciate any help!

That's interesting. It certainly doesn't look like that URI resolution should fail. (The fact that you get a weird message about r is not a constructor is certainly a SaxonJS bug: thank you!)
You said it "didn't work" when you tried it with relocation enabled, did it fail in exactly the same way?
I'm not personally familiar with exactly how React bundles a Node.JS version of a module into the browser (is that what it's doing!?). If it's practical for you to try loading the browser version of SaxonJS instead of the Node.js package, that might shed light on the situation.
I appreciate that this going to be a big ask, but if you can narrow this down to a small test case that I can reproduce, that will make it a lot easier to pin down.

Related

How to render bunch of XML files in JHipster React Application

I have a bunch of XML files( around 100 files) which I need to render it inside react application with proper navigation and styling.
These XMLs can have anchors to different XML files for navigation and also xml-stylesheet reference too. I have used JHipster's React Template for React app.
Now I want to use those static XML files and render it as HTML with React. Here is sample of one of the XML file with anchors and stylesheet reference too.
<?xml-stylesheet type="text/xsl" href="../vxml/styles/tmref.xslt"?>
<topic>
<metadata id="my_portal"
name="VoiceXML 2.0"
type="overview"
/>
<content>
<fm>
<p>Looking for technical information on using VoiceXML 2.0? This reference
will help guide you through ........
</p>
<ul class="ref">
<li>VoiceXML 2.0 Overview</li>
<li>VoiceXML 2.0 Element Reference</li>
<li>VoiceXML 2.0 Function Reference</li>
<li>VoiceXML 2.0 Object Reference</li>
</ul>
<note>You must upgrade that code to be compliant with VoiceXML 2.0
in order for it to continue to run on the <tvan/>.
Please refer to the Migration Guide for details.
</note>
</fm>
</content>
</topic>
Example for referenced tmref.xslt
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" />
<!-- location of common attribute data -->
<xsl:param name="common_attrs_uri" select="'vxml2_attrs_common.xml'"/>
<xsl:variable name="str_element_unsupported">Some static text</xsl:variable>
<xsl:template match="/">
<xsl:apply-templates select="/topic"/>
</xsl:template>
<xsl:include href="util.xslt"/>
<xsl:include href="refutil.xslt"/>
<xsl:include href="studio/reg_util.xslt"/>
<xsl:include href="globalparams.xslt"/>
<xsl:include href="grammar.xslt"/>
</xsl:stylesheet>
I have used couple for npm libraries for react in order to achieve the proper rendering but result of most of the tries were just XML as it is on browser screen instead of transformed version.

apache camel : generate random numeric ID in xslt

In apache camel, I am using xslt to create xml request. I want to generate random ID and pass it as RequestID as one of attribute. Is there any way to generate numeric ID in xslt.
<RequestID>12345</RequestID>
There are few conditions like number should contain only numeric value and no alphabets.
It should be maximum 8 digit.
FXSL (https://github.com/dnovatchev/FXSL-XSLT2) has pure XSLT 2 support for random numbers, I am struggling to find the right way to ensure the 8 digits but at least
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
expand-text="yes">
<xsl:import href="https://github.com/dnovatchev/FXSL-XSLT2/raw/master/Tests/test-random.xsl"/>
<xsl:variable name="random-number" as="xs:double">
<xsl:call-template name="randomSequence">
<xsl:with-param name="pLength" select="1"/>
<xsl:with-param name="pSeed" select="(current-dateTime() - xs:dateTime('1970-01-01T00:00:00')) div xs:dayTimeDuration('PT1S')"/>
<xsl:with-param name="pStart" select="1"/>
<xsl:with-param name="pEnd" select="100"/>
</xsl:call-template>
</xsl:variable>
<xsl:template match="/">
<RequestID>
<xsl:value-of select="format-number($random-number, '00000001')"/>
</RequestID>
</xsl:template>
</xsl:stylesheet>
gives a random number on each invocation. I am sure Dimitre will come along later to post a more informed answer on how to use his library for your case.

How do you use wsdl2java with an invalid wsdl file?

I am trying to use MSDN's MTPS, the API for accessing their MSDN content. If I just hand wsdl2java the url to their wsdl I get an NPE (CXF-5793). Daniel Kulp discovered that it is because they have an attribute called "messsage". There is an extra "s".
Cool.. So I search for renaming an attribute using xslt and I come up with this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*" />
</xsl:copy>
</xsl:template>
<xsl:template match="#messsage">
<xsl:attribute name="message">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
It turns out that I can't just point wsdl2java to a local file because the wsdl I'm trying to use has a bunch of <xsd:import> directives. So I made scripts to download those files.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output method="html" doctype-system="about:legacy-compat" />
<xsl:template match="/">
<html>
<head>
<title>XSD Imports for Wget to Fetch</title>
</head>
<body>
<div>This file is generated so that wget -i can download xsdimport'ed files.</div>
<xsl:for-each select="//xs:import">
<a>
<xsl:attribute name="href">
<xsl:value-of select="#schemaLocation" />
</xsl:attribute>
<xsl:value-of select="#schemaLocation" />
</a>
<br />
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
#!/bin/sh
wget -xNS http://services.msdn.microsoft.com/ContentServices/ContentService.asmx\?wsdl
xsltproc -o services.msdn.microsoft.com/ContentServices/fixedwsdl.xml messsage.xsl services.msdn.microsoft.com/ContentServices/ContentService.asmx\?wsdl
xsltproc -o wget.html wget.xsl services.msdn.microsoft.com/ContentServices/ContentService.asmx\?wsdl
wget -xNSF -i wget.html -B http://services.msdn.microsoft.com/ContentServices/ContentService.asmx\?wsdl
for filename in services.msdn.microsoft.com/ContentServices/schemas/*.xsd; do
xsltproc -o "$filename.html" wget.xsl $filename
wget -xNSF -i "$filename.html" -B http://services.msdn.microsoft.com/ContentServices/schemas/
done
for filename in services.msdn.microsoft.com/ContentServices/schemas/*.xsd; do
xsltproc -o "$filename.html" wget.xsl $filename
wget -xNSF -i "$filename.html" -B http://services.msdn.microsoft.com/ContentServices/schemas/
done
It doesn't work though. I guess it misses some of them and wsdl2java seems to want to find those scripts in the current working directory anyway. I don't know.
My question is, is there a way to get wsdl2java to apply a xml transformation to the wsdl file before using it? If not, should I continue down this road of using wget and stuff to download the files the wsdl depends on? I'm probably going to look into "flattening" the wsdl file next, but some people have said that <xsd:import>s can't be flattened like <xsd:include>s can. I feel like it is very unlikely that Microsoft can be convinced to fix the wsdl on their end. It appears that it has been this way for a very long time.
I'd be inclined to continue down the path of getting all the referenced schemas. I've used SoapUI to do it with other troublesome WSDLs. In the (rather old) version 3.6.1 I'm using, there is a function to "export definition" which should download all referenced schemas. Start by loading the corrected WSDL in SoapUI.
So.. What I did was add this proxy to my maven settings. (I'm using the maven plugin to generate these classes.)
<proxies>
<proxy>
<active>true</active>
<protocol>http</protocol>
<host>localhost</host>
<port>8080</port>
</proxy>
</proxies>
Then I ran
mitmproxy-2.7 --replace /~s/messsage/message
It works now. Talk about a build being platform dependent though heh...
Now to go and learn about how to use Web Services.
Thanks for the suggestion unhillbilly but I didn't know how to download every resource that this depended on.

How to write an XSL 1.0 stylesheet with a node-set() function that will run on both MSXML and libxml

I have an XSLT 1.0 stylesheet running using the XSL processor included with PHP (libxml). I want to get the same stylesheet to run on the Microsoft XSL processor MSXML 6.0 (msxml6.dll) ideally so the same stylesheet can run on either processor.
Unfortunately at the moment I would need to have two stylesheets - one for each processor.
This snippet invokes the node-set() function on the PHP processor;
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:template match="root">
<xsl:variable name="rtf">
<a>hello</a><b>world</b>
</xsl:variable>
<xsl:variable name="ns" select="exsl:node-set($rtf)"/>
<xsl:copy-of select="$ns/b"/>
</xsl:template>
</xsl:transform>
This snippet invokes the node-set() function on the Microsoft processor;
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
extension-element-prefixes="msxsl">
<xsl:template match="root">
<xsl:variable name="rtf">
<a>hello</a><b>world</b>
</xsl:variable>
<xsl:variable name="ns" select="msxsl:node-set($rtf)"/>
<xsl:copy-of select="$ns/b"/>
</xsl:template>
</xsl:transform>
If the input document was;
<root/>
The result of both stylesheets would be;
<b>world</b>
I want a single stylesheet that can run unchanged on the PHP processor and the Microsoft processor.
Although my real stylesheet is about 400 lines long and the the node-set() function is used in four places, I hope the examples above demonstrates the problem.
Checked on libxml and msxsl, works in both cases.
Regards
Mike.
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:func="http://exslt.org/functions"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
extension-element-prefixes="exsl func msxsl"
>
<func:function name="msxsl:node-set">
<xsl:param name="node"/>
<func:result select="exsl:node-set($node)"/>
</func:function>
<xsl:template match="root">
<xsl:variable name="rtf">
<a>hello</a><b>world</b>
</xsl:variable>
<xsl:variable name="ns" select="msxsl:node-set($rtf)"/>
<xsl:copy-of select="$ns/b"/>
</xsl:template>
</xsl:transform>

How to declare and iterate an array in XSLT?

My requirement is -using XSLT- to show a dropdown list with the US states and print 'selected' on one specific that is declared in the XML which will use my style sheet.
I was thinking on declare an array with the states and iterate it but I don't know how to do it.
NOTE: More ideas are welcome ;)
One way to do this is to embed the state data into the stylesheet itself, and access the stylesheet document using document(''), as follows:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="whatever"
exclude-result-prefixes="my">
<xsl:output indent="yes"/>
<!-- The value of the state you want to select, supplied in the input XML -->
<xsl:variable name="selected-state" select="/xpath/to/state/value"/>
<!-- You have to use a namespace, or the XSLT processor will complain -->
<my:states>
<option>Alabama</option>
<option>Alaska</option>
<!-- ... -->
<option>Wisconsin</option>
<option>Wyoming</option>
</my:states>
<xsl:template match="/">
<!-- rest of HTML -->
<select name="state">
<!-- Access the embedded document as an internal "config" file -->
<xsl:apply-templates select="document('')/*/my:states/option"/>
</select>
<!-- rest of HTML -->
</xsl:template>
<!-- Copy each option -->
<xsl:template match="option">
<xsl:copy>
<!-- Add selected="selected" if this is the one -->
<xsl:if test=". = $selected-state">
<xsl:attribute name="selected">selected</xsl:attribute>
</xsl:if>
<xsl:value-of select="."/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Let me know if you have any questions.
Ideally you would store the list of states in your XML file and just use XSLT to iterate them.
Update:
If you can't edit the XML, you could look at using the document function to load data from a second data file:

Resources