[英]Uncaught TypeError: Cannot read properties of null (reading 'hashCode') [SaxonJS]
I'm getting this error in Chrome console:我在 Chrome 控制台中收到此错误:
Seems to be a problem with XSLT or SEF as other SEF works.似乎是 XSLT 或其他 SEF 工作的 SEF 的问题。 I complie SEF with the xslt3
tool on Node.js version v14.17.3.我在 Node.js 版本 v14.17.3 上使用xslt3
工具编译 SEF。
I can run the XSLT with Saxon 9.8.12-EE in oXygen with no problem.我可以在 oXygen 中使用 Saxon 9.8.12-EE 运行 XSLT 没有问题。
Maybe the problem with maps, xsl:include
or xsl:import
?也许是地图、 xsl:include
或xsl:import
的问题?
Here is the XSLT code:这是 XSLT 代码:
<stylesheet exclude-result-prefixes="xs xd dme functx dita mei map array" extension-element-prefixes="ixsl" version="3.0" xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:array="http://www.w3.org/2005/xpath-functions/array" xmlns:dita="http://dita-ot.sourceforge.net" xmlns:dme="http://www.mozarteum.at/ns/dme" xmlns:functx="http://www.functx.com" xmlns:ixsl="http://saxonica.com/ns/interactiveXSLT" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:mei="http://www.music-encoding.org/ns/mei" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://www.music-encoding.org/ns/mei">
<xi:include href="docs.xsl" xpointer="element(/1/1)"/>
<import href="changeLog.xsl"/>
<!--This parameter is a needed for XSpec. Cf. https://github.com/xspec/xspec/wiki/Global-Context-Item-->
<param name="global-context-item" select="."/>
<param name="source"/>
<include href="../modules/identity-transform.xsl"/>
<xd:doc>
<xd:desc>
<xd:p>Replace current scoreDef with the alternative. Note that this should be defined in the following-sibling <choice>.</xd:p>
</xd:desc>
</xd:doc>
<template match="scoreDef[not(@corresp = concat('#', $source))]">
<copy-of select="following-sibling::choice[@type = 'scoring']/*[@corresp = concat('#', $source)]/scoreDef"/>
</template>
<xd:doc>
<xd:desc/>
</xd:doc>
<template match="choice[@type = 'scoring']"/>
<xd:doc>
<xd:desc>
<xd:p>Map staffDef@n of the new scoreDef and @dme.parts.</xd:p>
</xd:desc>
</xd:doc>
<variable as="map(xs:string, item())*" name="map_staves_order">
<for-each select="$global-context-item//choice[@type = 'scoring']/*[@corresp = concat('#', $source)]/scoreDef">
<map>
<for-each select="descendant::staffDef">
<map-entry key="string(@n)" select="@dme.parts"/>
</for-each>
</map>
</for-each>
</variable>
<xd:doc>
<xd:desc>
<xd:p>Get the maximum number of staves.</xd:p>
</xd:desc>
</xd:doc>
<variable as="xs:integer" name="count_staves" select="
max(for $a in map:keys($map_staves_order)
return
if (matches($a, '\d')) then
xs:integer($a)
else
())"/>
<xd:doc>
<xd:desc>
<xd:p>Key: old @n.</xd:p>
<xd:p>Value: new @n</xd:p>
</xd:desc>
</xd:doc>
<variable as="map(xs:string, xs:string)*" name="map_new_old_staves">
<map>
<for-each select="map:keys($map_staves_order)">
<variable name="current_key" select="."/>
<map-entry key="$global-context-item//measure[@n = 1]/staff[@dme.parts = map:get($map_staves_order, $current_key)]/@n/string()" select="."/>
</for-each>
</map>
</variable>
<xd:doc>
<xd:desc>
<xd:p>Copies elements before first staff without changes, e.g. <tempo></xd:p>
<xd:p>Copies staves accordingly to the new score order. Changes the @n-attribute accordingly</xd:p>
<xd:p>Copies ControlEvents and updates the @staff attribute if neccessary.</xd:p>
</xd:desc>
</xd:doc>
<template match="measure">
<copy>
<apply-templates select="@*"/>
<apply-templates select="child::staff[1]/preceding-sibling::*"/>
<variable as="element()" name="currentMeasure" select="."/>
<for-each select="1 to $count_staves">
<variable as="xs:string" name="currentItem" select="string()"/>
<for-each select="$currentMeasure/child::staff[map:get($map_staves_order, $currentItem) = @dme.parts]">
<copy>
<attribute name="n" select="$currentItem"/>
<apply-templates select="(@* except @n) | node()"/>
</copy>
</for-each>
</for-each>
<call-template name="update_staff_controlEvents">
<with-param name="elements" select="child::staff[last()]/following-sibling::*"/>
</call-template>
</copy>
</template>
<xd:doc>
<xd:desc>
<xd:p>Receives one or more elements (controlEvents) and updates their @staff according to the $map_new_old_staves variable.</xd:p>
<xd:p>Recursive template</xd:p>
</xd:desc>
<xd:param name="elements"/>
</xd:doc>
<template name="update_staff_controlEvents">
<param name="elements"/>
<for-each select="$elements">
<choose>
<when test="@staff">
<copy>
<attribute name="staff" select="map:get($map_new_old_staves, @staff)"/>
<apply-templates select="@* except @staff"/>
<if test="node()">
<call-template name="update_staff_controlEvents">
<with-param name="elements" select="node()"/>
</call-template>
</if>
</copy>
</when>
<otherwise>
<copy>
<apply-templates select="@*"/>
<if test="node()">
<call-template name="update_staff_controlEvents">
<with-param name="elements" select="node()"/>
</call-template>
</if>
</copy>
</otherwise>
</choose>
</for-each>
</template>
</stylesheet>
JS which I run on Console:我在控制台上运行的 JS:
var options = {
stylesheetLocation: "./assets/xsl/origScoring.sef.json",
sourceText: xmlString,
stylesheetParams: {"source": "source_A"},
destination: "document"
}
var result = SaxonJS.transform(options);
result.principalResult
Owing to the Saxon developers I could easily solve my issue by adding namespace prefixes in the XPath expressions when creating maps.由于Saxon 开发人员,我可以通过在创建地图时在 XPath 表达式中添加名称空间前缀轻松解决我的问题。 Originally, I used xpath-default-namespace
.最初,我使用xpath-default-namespace
。 Fo instance, here on the elements measure
and staff
should be:例如,这里的要素measure
和staff
应该是:
<map-entry key="$global-context-item//mei:measure[@n = 1]/mei:staff[@dme.parts = map:get($map_staves_order, $current_key)]/@n/string()" select="."/>
instead of代替
<map-entry key="$global-context-item//measure[@n = 1]/staff[@dme.parts = map:get($map_staves_order, $current_key)]/@n/string()" select="."/>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.