当我在XML文件上应用转换时,我得到了这个错误(即有效的布尔值未定义)。这里有一个奇怪的问题。
*我的应用程序从一个文件位置读取500到800个XML文件(XML文件大小从几KB到10MB不等),然后对每个文件进行转换。起初一切都很顺利,但在执行了一些程序后,它抛出了以下错误。
在productsFromLOC_v3.xsl的第651行出现错误:FORG0006。在xsl:call-template name="AssetStream" (file:C:appcompnfsservicestransformerproductsFromLOC_v3.xsl#378)处没有定义有效的布尔值。
第651行是 xsl:if test="fn:string-length( fn:copy-of($vStruct)) != 0"
一旦这个错误开始出现,而一个转变,其余所有的转变,然后导致同样的错误。
如果我选择那些错误的XML文件,然后单独处理,那么就没有任何问题。好像只有批量XML转换才会导致这个问题。
谁能帮助我解决这个问题?
Saxon EE 版本 - 9.8.0.7J,XSLT 版本 - 3.0。
Java代码。
private byte[] transformFromSource(String urlParams, String xslFullPath, final String uriXSLT,
final String outputXSLTFilePath, String transformParams, final Object xmlSource,
final String outputEncoding)
throws SaxonApiException, MalformedURLException, SystemException, UnsupportedEncodingException {
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
List<XsltExecutable> xsltExecutables = xsltTemplateManager.getTemplates(windowsOS ? xslFullPath.split("\\\\")[xslFullPath.split("\\\\").length - 1].trim() : xslFullPath.trim());
Processor processor = null;
XdmNode xdmNode = null;
XdmDestination xdmDestination1 = new XdmDestination();
XdmDestination xdmDestination2 = new XdmDestination();
for (XsltExecutable xsltExecutable : xsltExecutables) {
int i = 0;
final Xslt30Transformer transformer = xsltExecutable.load30();
final Map<QName, XdmValue> params = new HashMap<QName, XdmValue>();
if (StringUtils.isNotBlank(uriXSLT)) {
params.put(new QName("xslt.location.uriXSLTPath"), new XdmAtomicValue(uriXSLT));
}
if (StringUtils.isNotBlank(outputXSLTFilePath)) {
params.put(new QName("xslt.location.outputXSLTPath"), new XdmAtomicValue(outputXSLTFilePath));
}
if (StringUtils.isNotBlank(transformParams)) {
params.put(new QName("xslt.transform.params"), new XdmAtomicValue(transformParams));
}
if (StringUtils.isNotBlank(urlParams)) {
params.put(new QName("http.query.params"), new XdmAtomicValue(urlParams));
}
transformer.setStylesheetParameters(params);
if (xsltExecutables.size() == 1) {
processor = xsltExecutable.getProcessor();
if (xmlSource instanceof File) {
if (((File) xmlSource).isFile()) {
String inFile = "<file>" + ((File) xmlSource).getAbsolutePath() + "</file>";
xdmNode = processor.newDocumentBuilder().build(new StreamSource(new ByteArrayInputStream(inFile.getBytes(outputEncoding))));
}
} else {
xdmNode = processor.newDocumentBuilder().build((StreamSource) xmlSource);
}
final Serializer serializer = processor.newSerializer(outputStream);
/* serializer.setOutputProperty(Serializer.Property.METHOD, "xml"); */
serializer.setOutputProperty(Serializer.Property.INDENT, "yes");
serializer.setOutputProperty(Serializer.Property.ENCODING, outputEncoding);
transformer.applyTemplates(xdmNode, serializer);
} else if (xsltExecutables.size() > 1 && i == 0) {
processor = xsltExecutable.getProcessor();
if (xmlSource instanceof File) {
xdmNode = processor.newDocumentBuilder().build((File) xmlSource);
} else {
xdmNode = processor.newDocumentBuilder().build((StreamSource) xmlSource);
}
transformer.applyTemplates(xdmNode, xdmDestination1);
} else if (xsltExecutables.size() > 1 && i == xsltExecutables.size()) {
final Serializer serializer = processor.newSerializer(outputStream);
serializer.setOutputProperty(Serializer.Property.INDENT, "yes");
serializer.setOutputProperty(Serializer.Property.ENCODING, outputEncoding);
transformer.applyTemplates(xdmNode, serializer);
transformer.applyTemplates(xdmDestination2.getXdmNode(), serializer);
} else if (xsltExecutables.size() > 1 && i > 0) {
transformer.applyTemplates(xdmDestination1.getXdmNode(), xdmDestination2);
xdmDestination1 = xdmDestination2;
}
}
processor = null;
xdmNode = null;
xsltExecutables = null;
return outputStream.toByteArray(); }
XSLT的一部分,导致错误。
<xsl:iterate select="$STEP/STEP-ProductInformation/Assets/Asset[@UserTypeID='PDF' or @UserTypeID='PNG']">
<xsl:param name="vCount" select="1" as="xs:integer"/>
<xsl:param name="vFileCount" select="1" as="xs:integer"/>
<xsl:param name="vStruct" select="'' " as="xs:string"/>
<xsl:on-completion>
<xsl:variable name="vFileName" select="concat($outputXSLTFilePath,'/Asset-',$vTimestamp,'-',$vFileCount,$vJMSID,'.xml')"/>
<xsl:variable name="vResult">
<map xmlns="http://www.w3.org/2005/xpath-functions">
<array key="assets">
<xsl:copy-of select="$vStruct"/>
</array>
<string key="locale">
<xsl:value-of select="$vContextID"/>
</string>
<string key="exportTime">
<xsl:value-of select="$vExportTime"/>
</string>
</map>
</xsl:variable>
<xsl:if test="fn:string-length( fn:copy-of($vStruct)) ne 0">
<Payload>
<ControlData>
<FeedType>Assets</FeedType>
<FullImport>
<xsl:value-of select="$fullUpload"/>
</FullImport>
<Resequencing>true</Resequencing>
<JMSXGroupID>
<xsl:value-of select="$vJMSID"/>
</JMSXGroupID>
<JMSXGroupSeq>
<xsl:value-of select="$vFileCount"/>
</JMSXGroupSeq>
<GroupSize>
<xsl:value-of select="$vTotalMessages"/>
</GroupSize>
<OutboundQueueName>feeds/out/1.0/products</OutboundQueueName>
</ControlData>
<Message id="{$vFileCount}">
<xsl:value-of select="odfn:JsonBS(xml-to-json($vResult,map{ 'indent':true() }))"/>
</Message>
</Payload>
</xsl:if>
</xsl:on-completion>
<xsl:variable name="vX">
<map xmlns="http://www.w3.org/2005/xpath-functions">
<string key="id">
<xsl:value-of select="@ID"/>
</string>
<string key="typeId">
<xsl:value-of select="@UserTypeID"/>
</string>
<string key="filename">
<xsl:value-of select="./Values/Value[@AttributeID='asset.filename']"/>
</string>
</map>
</xsl:variable>
<xsl:variable name="vXS">
<xsl:copy-of select="$vStruct"/>
<xsl:copy-of select="$vX"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="$vCount < 50">
<xsl:next-iteration>
<xsl:with-param name="vCount" select="$vCount+1"/>
<xsl:with-param name="vFileCount" select="$vFileCount"/>
<xsl:with-param name="vStruct">
<xsl:copy-of select="$vXS"/>
</xsl:with-param>
</xsl:next-iteration>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="vFileName" select="concat($outputXSLTFilePath,'/Asset-',$vTimestamp,'-',$vFileCount,$vJMSID,'.xml')"/>
<xsl:variable name="vResult">
<map xmlns="http://www.w3.org/2005/xpath-functions">
<array key="assets">
<xsl:copy-of select="$vXS"/>
</array>
<string key="locale">
<xsl:value-of select="$vContextID"/>
</string>
<string key="exportTime">
<xsl:value-of select="$vExportTime"/>
</string>
</map>
</xsl:variable>
<Payload>
<ControlData>
<FeedType>Assets</FeedType>
<FullImport>
<xsl:value-of select="$fullUpload"/>
</FullImport>
<Resequencing>true</Resequencing>
<JMSXGroupID>
<xsl:value-of select="$vJMSID"/>
</JMSXGroupID>
<JMSXGroupSeq>
<xsl:value-of select="$vFileCount"/>
</JMSXGroupSeq>
<GroupSize>
<xsl:value-of select="$vTotalMessages"/>
</GroupSize>
<OutboundQueueName>feeds/out/1.0/products</OutboundQueueName>
</ControlData>
<Message id="{$vFileCount}">
<xsl:value-of select="odfn:JsonBS(xml-to-json($vResult,map{ 'indent':true() }))"/>
</Message>
</Payload>
<xsl:next-iteration>
<xsl:with-param name="vCount" select="1"/>
<xsl:with-param name="vFileCount" select="$vFileCount+1"/>
<xsl:with-param name="vStruct" select="''"/>
<!-- blank -->
</xsl:next-iteration>
</xsl:otherwise>
</xsl:choose>
作为实验,请关闭字节码的生成。(FeatureKeys.GENERATE_BYTE_CODE
)
当一个构造体被执行到一定次数时,字节码生成就会启动,这与您的观察一致,即只有在运行一定数量的变换后才会出现故障,如果您单独运行这些变换就不会出现。
我认为问题很有可能是由不正确的字节码生成引起的。如果事实证明是这样,我们显然希望您能帮助我们找到实际的错误(而不仅仅是绕过它):为此,请尝试使用较低的字节码生成阈值运行,以便它能更快地启动 (FeatureKeys.THESHOLD_FOR_HOTSPOT_BYTECODE
).
我也鼓励你在Saxon 10.0上试试。这完全有可能是一个已经修复的bug。