累加器不适用于当前带有 Saxon PE 的文档 9-9-1-5 Java
Accumulator is not applicable to the current document with Saxon PE 9-9-1-5 Java
我有一个输入 XML:
<?xml version='1.0' encoding='UTF-8'?>
<MessageFormat name='TransportEvent' version='2.02'>
<StructFormat name='TransportEventHeader' >
<TagField type='String' value='H0 '/>
<FieldFormat name='NotificationTriggeringOU' length='10'/>
<FieldFormat name='NotificationTriggeringIT' length='8'/>
<FieldFormat name='NotificationReference' length='1'/>
<FieldFormat name='NotificationCode' length='3'/>
<FieldFormat name='NotificationType' length='8'/>
<FieldFormat name='NotificationStatus' length='1'/>
<FieldFormat name='NotificationTripType' length='1'/>
<FieldFormat name='ProducingRailwayUndertaking' length='4'/>
<FieldFormat name='ExternalPartner' length='35'/>
<FieldFormat name='ActualNumberOfWagons' length='3' />
<FieldFormat name='ProcessingTime' length='26'/>
<StructFormat name='NotificationFunctionalClassification'>
<FieldFormat name='OrderRelevant' length='1'/>
<FieldFormat name='TimetableRelevant' length='1'/>
<FieldFormat name='CapacityRelevant' length='1'/>
<FieldFormat name='IntermodalRelevant' length='1'/>
<FieldFormat name='XrailRelevant' length='1'/>
<FieldFormat name='NotificationLocationRelevant' length='1'/>
</StructFormat>
<FieldFormat name='Reserve' length='1'/>
</StructFormat>
<StructFormat name='NotificationLocation' >
<TagField type='String' value='M1 '/>
<StructFormat name='CurrentLocation'>
<FieldFormat name='CurrentLocationRL100' length='5'/>
<FieldFormat name='CurrentLocationLocationType' length='1'/>
<FieldFormat name='CurrentUICRailAuthorityNumber' length='6'/>
<FieldFormat name='CurrentNetworkLocationNumber' length='6'/>
<FieldFormat name='CurrentLocationSatelliteNumber' length='2'/>
<FieldFormat name='CurrentFreightCarLocationNumber' length='4'/>
</StructFormat>
<StructFormat name='NextLocation'>
<FieldFormat name='NextLocationRL100' length='5'/>
<FieldFormat name='NextLocationLocationType' length='1'/>
<FieldFormat name='NextUICRailAuthorityNumber' length='6'/>
<FieldFormat name='NextNetworkLocationNumber' length='6'/>
<FieldFormat name='NextLocationSatelliteNumber' length='2'/>
<FieldFormat name='NextFreightCarLocationNumber' length='4'/>
</StructFormat>
</StructFormat>
<StructFormat name='NotificationTime' >
<TagField type='String' value='M2 '/>
<FieldFormat name='ActualTime' length='18'/>
</StructFormat>
<StructFormat name='Trip' >
<TagField type='String' value='Z1 '/>
<FieldFormat name='TripNumber' length='6'/>
<FieldFormat name='RegionNetz' length='2'/>
<FieldFormat name='NationalProductionDate' length='10'/>
<FieldFormat name='TrainTypeMainNumber' length='2'/>
<FieldFormat name='TrainTypeSubNumber' length='1'/>
<FieldFormat name='DepartureStationRL100' length='5'/>
<FieldFormat name='DepartureStationUICRailAuthority' length='6'/>
<FieldFormat name='DepartureStationNetworkLocation' length='6'/>
<FieldFormat name='TargetTime' length='18'/>
<FieldFormat name='RelativeTime' length='5' />
</StructFormat>
<StructFormat name='HandoverTakeover' >
<TagField type='String' value='U1 '/>
<FieldFormat name='HandoverTakeoverFlag' length='1'/>
<FieldFormat name='ConsigningRU' length='4'/>
<FieldFormat name='AcceptingRU' length='4'/>
<FieldFormat name='UICBorderCode' length='3'/>
</StructFormat>
</MessageFormat>
在我的 xslt 模板中,我想计算直接在 MessageFormat 下的每个 StructFormat 的 (FieldFormat/@length + string-length(TagField/@value):
<?xml version="1.0" encoding="UTF-8"?>
<?altova_samplexml format.xml?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:array="http://www.w3.org/2005/xpath-functions/array" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:err="http://www.w3.org/2005/xqt-errors" xmlns:saxon="http://saxon.sf.net/" exclude-result-prefixes="array fn map math xhtml xs err" version="3.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="msg">H0 EVU_DBSRD PVG W14 PVGERL I 0142019-12-08-07.46.52.436704NNJNNJNM1 80270611 04401 M2 08.12.201907:50:00Z1 BAU1 08.12.2019 08.12.201907:50:00 0000R1 00131806940728280201912063946287201912061215058175346965 000NNJNNN 80270611 04401R1 00231806940476880201912063946287201912061215059494346965 000NNJNNN 80270611 04401R1 00331806948174180201912063946287201912061215050425346965 000NNJNNN 80270611 04401R1 00431806948098280201912063946287201912061215051864346965 000NNJNNN 80270611 04401</xsl:variable>
<xsl:accumulator name="position-count" as="xs:double" initial-value="1" streamable="no">
<xsl:accumulator-rule match="/MessageFormat/StructFormat" phase="end" select="$value +sum(.//FieldFormat/@length) + string-length(./TagField/@value)" />
</xsl:accumulator>
<xsl:template match="/">
<output>
<xsl:for-each select="/MessageFormat/StructFormat">
<xsl:element name="{./@name}">
<xsl:attribute name="start" select="fn:accumulator-before('position-count')"/>
<xsl:attribute name="end" select="fn:accumulator-after('position-count')" />
</xsl:element>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
当我 运行 使用 XML Spy Professional 2020 SP1 时,我得到输出:
<?xml version="1.0" encoding="UTF-8"?>
<output xmlns:saxon="http://saxon.sf.net/">
<TransportEventHeader start="1" end="111"/>
<NotificationLocation start="111" end="162"/>
<NotificationTime start="162" end="183"/>
<Trip start="183" end="247"/>
<HandoverTakeover start="247" end="262"/>
</output>
但是当我 运行 它与 Saxon 9-9-1-5 Java java -cp /d/SaxonPE9-9-1-5J/saxon9pe.jar net.sf.saxon.Transform -s:format.xml -xsl:accumulator.xslt -o:output.xml
我收到错误:
Error evaluating (fn:accumulator-before(...)) in xsl:attribute/@select
on line 13 column 83 of accumulator.xslt: XTDE3362: Accumulator
position-count is not applicable to the current document
invoked by unknown caller (class net.sf.saxon.expr.instruct.ForEach) at
file:/D:/xslt/accumulator.xslt#11
In template rule with match="/" on line 9 of accumulator.xslt
Accumulator position-count is not applicable to the current document
我的蓄电池有什么问题?为什么它适用于 XML Spy,而不适用于 Saxon 9.9?
实际上我想在我的累加器中添加一个条件来检查变量 $msg
中的值 TagField/@value
是否在正确的位置出现。
比如StructFormat[@name='TransportEventHeader']
,$msg的前3个字符是"H0 ",所以它匹配StructFormat[@name='TransportEventHeader']/TagField/@value
,这种情况下应该把长度加到我的累加器中,如果不是,则不应添加。我不知道如何在累加器中实现它。
规则在这里:https://www.w3.org/TR/xslt-30/#applicability-of-accumulators
规则 5 说:对于包含在初始匹配选择中提供的节点的文档,适用的累加器是由初始模式的 xsl:mode 声明确定的。这意味着在没有 xsl:mode 声明的情况下,没有适用的累加器。
所以你需要添加
<xsl:mode use-accumulators="position-count"/>
规范中制定这些规则的原因是 (a) 对于流式处理,如果不打算在该文档上使用它,则为流式处理文档维护累加器的成本很高,并且 (b) 尽管非流式文档不存在相同的开销,因为可以在首次使用时评估累加器,因此人们认为无论文档是流式还是非流式,都希望有相同的规则。
Altova 没有实现流式传输,所以他们可能认为(并且有一些理由,我会同意)实现规则需要付出很多努力,但对用户的价值很小。
Michael Kay 已经回答了我的问题。问题最初来自应用累加器。现在我得到一个像下面这样的工作累加器来计算组位置:
<xsl:accumulator-rule match="/MessageFormat/StructFormat" phase="end">
<xsl:choose>
<xsl:when test="substring($msg, $value, string-length(./TagField/@value)) = ./TagField/@value">
<xsl:value-of select="$value + xs:integer(sum(.//FieldFormat/@length)) + string-length(./TagField/@value)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:accumulator-rule>
</xsl:accumulator>
我有一个输入 XML:
<?xml version='1.0' encoding='UTF-8'?>
<MessageFormat name='TransportEvent' version='2.02'>
<StructFormat name='TransportEventHeader' >
<TagField type='String' value='H0 '/>
<FieldFormat name='NotificationTriggeringOU' length='10'/>
<FieldFormat name='NotificationTriggeringIT' length='8'/>
<FieldFormat name='NotificationReference' length='1'/>
<FieldFormat name='NotificationCode' length='3'/>
<FieldFormat name='NotificationType' length='8'/>
<FieldFormat name='NotificationStatus' length='1'/>
<FieldFormat name='NotificationTripType' length='1'/>
<FieldFormat name='ProducingRailwayUndertaking' length='4'/>
<FieldFormat name='ExternalPartner' length='35'/>
<FieldFormat name='ActualNumberOfWagons' length='3' />
<FieldFormat name='ProcessingTime' length='26'/>
<StructFormat name='NotificationFunctionalClassification'>
<FieldFormat name='OrderRelevant' length='1'/>
<FieldFormat name='TimetableRelevant' length='1'/>
<FieldFormat name='CapacityRelevant' length='1'/>
<FieldFormat name='IntermodalRelevant' length='1'/>
<FieldFormat name='XrailRelevant' length='1'/>
<FieldFormat name='NotificationLocationRelevant' length='1'/>
</StructFormat>
<FieldFormat name='Reserve' length='1'/>
</StructFormat>
<StructFormat name='NotificationLocation' >
<TagField type='String' value='M1 '/>
<StructFormat name='CurrentLocation'>
<FieldFormat name='CurrentLocationRL100' length='5'/>
<FieldFormat name='CurrentLocationLocationType' length='1'/>
<FieldFormat name='CurrentUICRailAuthorityNumber' length='6'/>
<FieldFormat name='CurrentNetworkLocationNumber' length='6'/>
<FieldFormat name='CurrentLocationSatelliteNumber' length='2'/>
<FieldFormat name='CurrentFreightCarLocationNumber' length='4'/>
</StructFormat>
<StructFormat name='NextLocation'>
<FieldFormat name='NextLocationRL100' length='5'/>
<FieldFormat name='NextLocationLocationType' length='1'/>
<FieldFormat name='NextUICRailAuthorityNumber' length='6'/>
<FieldFormat name='NextNetworkLocationNumber' length='6'/>
<FieldFormat name='NextLocationSatelliteNumber' length='2'/>
<FieldFormat name='NextFreightCarLocationNumber' length='4'/>
</StructFormat>
</StructFormat>
<StructFormat name='NotificationTime' >
<TagField type='String' value='M2 '/>
<FieldFormat name='ActualTime' length='18'/>
</StructFormat>
<StructFormat name='Trip' >
<TagField type='String' value='Z1 '/>
<FieldFormat name='TripNumber' length='6'/>
<FieldFormat name='RegionNetz' length='2'/>
<FieldFormat name='NationalProductionDate' length='10'/>
<FieldFormat name='TrainTypeMainNumber' length='2'/>
<FieldFormat name='TrainTypeSubNumber' length='1'/>
<FieldFormat name='DepartureStationRL100' length='5'/>
<FieldFormat name='DepartureStationUICRailAuthority' length='6'/>
<FieldFormat name='DepartureStationNetworkLocation' length='6'/>
<FieldFormat name='TargetTime' length='18'/>
<FieldFormat name='RelativeTime' length='5' />
</StructFormat>
<StructFormat name='HandoverTakeover' >
<TagField type='String' value='U1 '/>
<FieldFormat name='HandoverTakeoverFlag' length='1'/>
<FieldFormat name='ConsigningRU' length='4'/>
<FieldFormat name='AcceptingRU' length='4'/>
<FieldFormat name='UICBorderCode' length='3'/>
</StructFormat>
</MessageFormat>
在我的 xslt 模板中,我想计算直接在 MessageFormat 下的每个 StructFormat 的 (FieldFormat/@length + string-length(TagField/@value):
<?xml version="1.0" encoding="UTF-8"?>
<?altova_samplexml format.xml?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:array="http://www.w3.org/2005/xpath-functions/array" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:err="http://www.w3.org/2005/xqt-errors" xmlns:saxon="http://saxon.sf.net/" exclude-result-prefixes="array fn map math xhtml xs err" version="3.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="msg">H0 EVU_DBSRD PVG W14 PVGERL I 0142019-12-08-07.46.52.436704NNJNNJNM1 80270611 04401 M2 08.12.201907:50:00Z1 BAU1 08.12.2019 08.12.201907:50:00 0000R1 00131806940728280201912063946287201912061215058175346965 000NNJNNN 80270611 04401R1 00231806940476880201912063946287201912061215059494346965 000NNJNNN 80270611 04401R1 00331806948174180201912063946287201912061215050425346965 000NNJNNN 80270611 04401R1 00431806948098280201912063946287201912061215051864346965 000NNJNNN 80270611 04401</xsl:variable>
<xsl:accumulator name="position-count" as="xs:double" initial-value="1" streamable="no">
<xsl:accumulator-rule match="/MessageFormat/StructFormat" phase="end" select="$value +sum(.//FieldFormat/@length) + string-length(./TagField/@value)" />
</xsl:accumulator>
<xsl:template match="/">
<output>
<xsl:for-each select="/MessageFormat/StructFormat">
<xsl:element name="{./@name}">
<xsl:attribute name="start" select="fn:accumulator-before('position-count')"/>
<xsl:attribute name="end" select="fn:accumulator-after('position-count')" />
</xsl:element>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
当我 运行 使用 XML Spy Professional 2020 SP1 时,我得到输出:
<?xml version="1.0" encoding="UTF-8"?>
<output xmlns:saxon="http://saxon.sf.net/">
<TransportEventHeader start="1" end="111"/>
<NotificationLocation start="111" end="162"/>
<NotificationTime start="162" end="183"/>
<Trip start="183" end="247"/>
<HandoverTakeover start="247" end="262"/>
</output>
但是当我 运行 它与 Saxon 9-9-1-5 Java java -cp /d/SaxonPE9-9-1-5J/saxon9pe.jar net.sf.saxon.Transform -s:format.xml -xsl:accumulator.xslt -o:output.xml
我收到错误:
Error evaluating (fn:accumulator-before(...)) in xsl:attribute/@select on line 13 column 83 of accumulator.xslt: XTDE3362: Accumulator position-count is not applicable to the current document invoked by unknown caller (class net.sf.saxon.expr.instruct.ForEach) at file:/D:/xslt/accumulator.xslt#11 In template rule with match="/" on line 9 of accumulator.xslt Accumulator position-count is not applicable to the current document
我的蓄电池有什么问题?为什么它适用于 XML Spy,而不适用于 Saxon 9.9?
实际上我想在我的累加器中添加一个条件来检查变量 $msg
中的值 TagField/@value
是否在正确的位置出现。
比如StructFormat[@name='TransportEventHeader']
,$msg的前3个字符是"H0 ",所以它匹配StructFormat[@name='TransportEventHeader']/TagField/@value
,这种情况下应该把长度加到我的累加器中,如果不是,则不应添加。我不知道如何在累加器中实现它。
规则在这里:https://www.w3.org/TR/xslt-30/#applicability-of-accumulators
规则 5 说:对于包含在初始匹配选择中提供的节点的文档,适用的累加器是由初始模式的 xsl:mode 声明确定的。这意味着在没有 xsl:mode 声明的情况下,没有适用的累加器。
所以你需要添加
<xsl:mode use-accumulators="position-count"/>
规范中制定这些规则的原因是 (a) 对于流式处理,如果不打算在该文档上使用它,则为流式处理文档维护累加器的成本很高,并且 (b) 尽管非流式文档不存在相同的开销,因为可以在首次使用时评估累加器,因此人们认为无论文档是流式还是非流式,都希望有相同的规则。
Altova 没有实现流式传输,所以他们可能认为(并且有一些理由,我会同意)实现规则需要付出很多努力,但对用户的价值很小。
Michael Kay 已经回答了我的问题。问题最初来自应用累加器。现在我得到一个像下面这样的工作累加器来计算组位置:
<xsl:accumulator-rule match="/MessageFormat/StructFormat" phase="end">
<xsl:choose>
<xsl:when test="substring($msg, $value, string-length(./TagField/@value)) = ./TagField/@value">
<xsl:value-of select="$value + xs:integer(sum(.//FieldFormat/@length)) + string-length(./TagField/@value)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:accumulator-rule>
</xsl:accumulator>