using accumulator-rule to remember context info - xslt

Short question:
why my xsl:accumulator-rule
<xsl:when test="substring($msg, $value, string-length(./TagField/#value)) != ./TagField/#value"> doesn't work with Saxon PE 9.9, but works with XSL Professional 2020 sp1. The error reported by Saxon is:
Error evaluating (fn:accumulator-before(...) =
fn:accumulator-after(...)) in xsl:when/#test on line 45 column 100 of
format.xslt: XPTY0004: An empty sequence is not allowed as the
second argument of fn:substring(). Found while atomizing the first
operand of '=' In template rule with match="pattern matching
node()/element(Q{}MessageFormat)/element(Q{}StructFormat)[(not(attribute::attribute(Q{}repeat)))
and child::element(Q{}TagField)]" on line 82 of format.xslt
invoked by built-in template rule (shallow-copy)
invoked by xsl:apply-templates at file:/D:/issue/pfr-transportevent-v01/config/transformation/xslt/format.xslt#102
at procedure complete-struct on line 101 of format.xslt:
invoked by global xsl:variable In template rule with match="/" on line 104 of format.xslt An empty sequence is not allowed as the
second argument of fn:substring(). Found while atomizing the first
operand of '='
Here is my complete xsl:accumulator
<xsl:accumulator name="position-count" as="xs:integer?" initial-value="1" streamable="no">
<xsl:accumulator-rule match="$MFL/MessageFormat/StructFormat" phase="end">
<xsl:choose>
<xsl:when test="./#repeat = '*' ">
<xsl:choose>
<xsl:when test="substring($msg, $value, string-length(./TagField/#value)) != ./TagField/#value">
<xsl:sequence select="$value"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="repeat" select="count(tokenize(fn:substring($msg, $value) , ./TagField/#value)) - 1"/>
<xsl:sequence select="$value + map:get($groupsize, ./#name) * $repeat"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="substring($msg, $value, string-length(./TagField/#value)) = ./TagField/#value">
<!--<xsl:sequence select="$value + xs:integer(sum(.//FieldFormat/#length)) + string-length(./TagField/#value)"/>-->
<xsl:sequence select="$value + map:get($groupsize, string(./#name))"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:accumulator-rule>
</xsl:accumulator>
Backgroud:
I have to solve following problem, the input is plain text with variable length, for example
"H0 EVU_DBSRD PVG Z24 ABF-RF IR 0112019-12-10-14.46.18.553122NJJNNJNM1 80142455360001 M2 10.12.201914:40:00Z1 RABWR1 10.12.2019 10.12.201914:40:00 0000R1 00133807843874880201912103988789201912101530419325346965 000 NN R1 002338078480716 201912101446013716142455 000 NN R1 00324714370125580201912103961427201912101200186865346965 000 NN R1 00433807840438580201912103984329201912101530381256346965 000 NN R1 00524714273013180201912093997400201912090900494682346965 000 NN R1 00637847829609880201912104006488201912101530572232346965 000 NN R1 00737807836474280201912103954824201912101530128369346965 000 NN R1 008338079134858 201912101446013858142455 000 NN R1 00933807849379280201912103979328201912101530334318346965 000 NN R1 01037847829649480201912103990982201912101530433292346965 000 NN R1 011338078414616 201912101446013616142455 000 NN "
( I put the text in quote to keep spaces after last character N)
The expected out is following:
<?xml version="1.0" encoding="UTF-8"?>
<TransportEvent>
<TransportEventHeader>
<NotificationTriggeringOU>EVU_DBSRD</NotificationTriggeringOU>
<NotificationTriggeringIT>PVG</NotificationTriggeringIT>
<NotificationReference>Z</NotificationReference>
<NotificationCode>24</NotificationCode>
<NotificationType>ABF-RF</NotificationType>
<NotificationStatus>I</NotificationStatus>
<NotificationTripType>R</NotificationTripType>
<ProducingRailwayUndertaking/>
<ExternalPartner> </ExternalPartner>
<ActualNumberOfWagons>11</ActualNumberOfWagons>
<ProcessingTime>2019-12-10-14.46.18.553122</ProcessingTime>
<NotificationFunctionalClassification>
<OrderRelevant>N</OrderRelevant>
<TimetableRelevant>J</TimetableRelevant>
<CapacityRelevant>J</CapacityRelevant>
<IntermodalRelevant>N</IntermodalRelevant>
<XrailRelevant>N</XrailRelevant>
<NotificationLocationRelevant>J</NotificationLocationRelevant>
</NotificationFunctionalClassification>
<Reserve>N</Reserve>
</TransportEventHeader>
<NotificationLocation>
<CurrentLocation>
<CurrentLocationRL100/>
<CurrentLocationLocationType/>
<CurrentUICRailAuthorityNumber> 80</CurrentUICRailAuthorityNumber>
<CurrentNetworkLocationNumber>142455</CurrentNetworkLocationNumber>
<CurrentLocationSatelliteNumber>36</CurrentLocationSatelliteNumber>
<CurrentFreightCarLocationNumber>0001</CurrentFreightCarLocationNumber>
</CurrentLocation>
<NextLocation>
<NextLocationRL100/>
<NextLocationLocationType/>
<NextUICRailAuthorityNumber/>
<NextNetworkLocationNumber/>
<NextLocationSatelliteNumber/>
<NextFreightCarLocationNumber/>
</NextLocation>
</NotificationLocation>
<NotificationTime>
<ActualTime>10.12.201914:40:00</ActualTime>
</NotificationTime>
<Trip>
<TripNumber>RABWR1</TripNumber>
<RegionDBNetz/>
<NationalProductionDate>10.12.2019</NationalProductionDate>
<TrainTypeMainNumber/>
<TrainTypeSubNumber/>
<DepartureStationRL100/>
<DepartureStationUICRailAuthority/>
<DepartureStationNetworkLocation/>
<TargetTime>10.12.201914:40:00</TargetTime>
<RelativeTime> 0000</RelativeTime>
</Trip>
<Ordering>
<OrderingPosition>1</OrderingPosition>
<OrderingVehicleNumber>338078438748</OrderingVehicleNumber>
<OrderingCommercialOrderKey>80201912103988789</OrderingCommercialOrderKey>
<OrderingProductionOrderKey>201912101530419325346965</OrderingProductionOrderKey>
<OrderingConsignmentNumberID/>
<OrderingTrainGroup>0</OrderingTrainGroup>
<FlagActivation/>
<FlagClosing/>
<FlagCompletion/>
<FlagSuspended/>
<WagonIntermodal>N</WagonIntermodal>
<OderIntermodal>N</OderIntermodal>
<Activation>
<ActivationRL100Location/>
<ActivationLocationLocationType/>
<ActivationUICRailAuthorityLocationNumber/>
<ActivationNetworkLocationNumber/>
<ActivationSatelliteLocationNumber/>
<ActivationFreightCarLocationNumber/>
</Activation>
<Completion>
<CompletionRL100Location/>
<CompletionLocationLocationType/>
<CompletionUICRailAuthorityLocationNumber/>
<CompletionNetworkLocationNumber/>
<CompletionSatelliteLocationNumber/>
<CompletionFreightCarLocationNumber/>
</Completion>
</Ordering>
<Ordering>
<OrderingPosition>2</OrderingPosition>
<OrderingVehicleNumber>338078480716</OrderingVehicleNumber>
<OrderingCommercialOrderKey/>
<OrderingProductionOrderKey>201912101446013716142455</OrderingProductionOrderKey>
<OrderingConsignmentNumberID/>
<OrderingTrainGroup>0</OrderingTrainGroup>
<FlagActivation/>
<FlagClosing/>
<FlagCompletion/>
<FlagSuspended/>
<WagonIntermodal>N</WagonIntermodal>
<OderIntermodal>N</OderIntermodal>
<Activation>
<ActivationRL100Location/>
<ActivationLocationLocationType/>
<ActivationUICRailAuthorityLocationNumber/>
<ActivationNetworkLocationNumber/>
<ActivationSatelliteLocationNumber/>
<ActivationFreightCarLocationNumber/>
</Activation>
<Completion>
<CompletionRL100Location/>
<CompletionLocationLocationType/>
<CompletionUICRailAuthorityLocationNumber/>
<CompletionNetworkLocationNumber/>
<CompletionSatelliteLocationNumber/>
<CompletionFreightCarLocationNumber/>
</Completion>
</Ordering>
<Ordering>
<OrderingPosition>3</OrderingPosition>
<OrderingVehicleNumber>247143701255</OrderingVehicleNumber>
<OrderingCommercialOrderKey>80201912103961427</OrderingCommercialOrderKey>
<OrderingProductionOrderKey>201912101200186865346965</OrderingProductionOrderKey>
<OrderingConsignmentNumberID/>
<OrderingTrainGroup>0</OrderingTrainGroup>
<FlagActivation/>
<FlagClosing/>
<FlagCompletion/>
<FlagSuspended/>
<WagonIntermodal>N</WagonIntermodal>
<OderIntermodal>N</OderIntermodal>
<Activation>
<ActivationRL100Location/>
<ActivationLocationLocationType/>
<ActivationUICRailAuthorityLocationNumber/>
<ActivationNetworkLocationNumber/>
<ActivationSatelliteLocationNumber/>
<ActivationFreightCarLocationNumber/>
</Activation>
<Completion>
<CompletionRL100Location/>
<CompletionLocationLocationType/>
<CompletionUICRailAuthorityLocationNumber/>
<CompletionNetworkLocationNumber/>
<CompletionSatelliteLocationNumber/>
<CompletionFreightCarLocationNumber/>
</Completion>
</Ordering>
<Ordering>
<OrderingPosition>4</OrderingPosition>
<OrderingVehicleNumber>338078404385</OrderingVehicleNumber>
<OrderingCommercialOrderKey>80201912103984329</OrderingCommercialOrderKey>
<OrderingProductionOrderKey>201912101530381256346965</OrderingProductionOrderKey>
<OrderingConsignmentNumberID/>
<OrderingTrainGroup>0</OrderingTrainGroup>
<FlagActivation/>
<FlagClosing/>
<FlagCompletion/>
<FlagSuspended/>
<WagonIntermodal>N</WagonIntermodal>
<OderIntermodal>N</OderIntermodal>
<Activation>
<ActivationRL100Location/>
<ActivationLocationLocationType/>
<ActivationUICRailAuthorityLocationNumber/>
<ActivationNetworkLocationNumber/>
<ActivationSatelliteLocationNumber/>
<ActivationFreightCarLocationNumber/>
</Activation>
<Completion>
<CompletionRL100Location/>
<CompletionLocationLocationType/>
<CompletionUICRailAuthorityLocationNumber/>
<CompletionNetworkLocationNumber/>
<CompletionSatelliteLocationNumber/>
<CompletionFreightCarLocationNumber/>
</Completion>
</Ordering>
<Ordering>
<OrderingPosition>5</OrderingPosition>
<OrderingVehicleNumber>247142730131</OrderingVehicleNumber>
<OrderingCommercialOrderKey>80201912093997400</OrderingCommercialOrderKey>
<OrderingProductionOrderKey>201912090900494682346965</OrderingProductionOrderKey>
<OrderingConsignmentNumberID/>
<OrderingTrainGroup>0</OrderingTrainGroup>
<FlagActivation/>
<FlagClosing/>
<FlagCompletion/>
<FlagSuspended/>
<WagonIntermodal>N</WagonIntermodal>
<OderIntermodal>N</OderIntermodal>
<Activation>
<ActivationRL100Location/>
<ActivationLocationLocationType/>
<ActivationUICRailAuthorityLocationNumber/>
<ActivationNetworkLocationNumber/>
<ActivationSatelliteLocationNumber/>
<ActivationFreightCarLocationNumber/>
</Activation>
<Completion>
<CompletionRL100Location/>
<CompletionLocationLocationType/>
<CompletionUICRailAuthorityLocationNumber/>
<CompletionNetworkLocationNumber/>
<CompletionSatelliteLocationNumber/>
<CompletionFreightCarLocationNumber/>
</Completion>
</Ordering>
<Ordering>
<OrderingPosition>6</OrderingPosition>
<OrderingVehicleNumber>378478296098</OrderingVehicleNumber>
<OrderingCommercialOrderKey>80201912104006488</OrderingCommercialOrderKey>
<OrderingProductionOrderKey>201912101530572232346965</OrderingProductionOrderKey>
<OrderingConsignmentNumberID/>
<OrderingTrainGroup>0</OrderingTrainGroup>
<FlagActivation/>
<FlagClosing/>
<FlagCompletion/>
<FlagSuspended/>
<WagonIntermodal>N</WagonIntermodal>
<OderIntermodal>N</OderIntermodal>
<Activation>
<ActivationRL100Location/>
<ActivationLocationLocationType/>
<ActivationUICRailAuthorityLocationNumber/>
<ActivationNetworkLocationNumber/>
<ActivationSatelliteLocationNumber/>
<ActivationFreightCarLocationNumber/>
</Activation>
<Completion>
<CompletionRL100Location/>
<CompletionLocationLocationType/>
<CompletionUICRailAuthorityLocationNumber/>
<CompletionNetworkLocationNumber/>
<CompletionSatelliteLocationNumber/>
<CompletionFreightCarLocationNumber/>
</Completion>
</Ordering>
<Ordering>
<OrderingPosition>7</OrderingPosition>
<OrderingVehicleNumber>378078364742</OrderingVehicleNumber>
<OrderingCommercialOrderKey>80201912103954824</OrderingCommercialOrderKey>
<OrderingProductionOrderKey>201912101530128369346965</OrderingProductionOrderKey>
<OrderingConsignmentNumberID/>
<OrderingTrainGroup>0</OrderingTrainGroup>
<FlagActivation/>
<FlagClosing/>
<FlagCompletion/>
<FlagSuspended/>
<WagonIntermodal>N</WagonIntermodal>
<OderIntermodal>N</OderIntermodal>
<Activation>
<ActivationRL100Location/>
<ActivationLocationLocationType/>
<ActivationUICRailAuthorityLocationNumber/>
<ActivationNetworkLocationNumber/>
<ActivationSatelliteLocationNumber/>
<ActivationFreightCarLocationNumber/>
</Activation>
<Completion>
<CompletionRL100Location/>
<CompletionLocationLocationType/>
<CompletionUICRailAuthorityLocationNumber/>
<CompletionNetworkLocationNumber/>
<CompletionSatelliteLocationNumber/>
<CompletionFreightCarLocationNumber/>
</Completion>
</Ordering>
<Ordering>
<OrderingPosition>8</OrderingPosition>
<OrderingVehicleNumber>338079134858</OrderingVehicleNumber>
<OrderingCommercialOrderKey/>
<OrderingProductionOrderKey>201912101446013858142455</OrderingProductionOrderKey>
<OrderingConsignmentNumberID/>
<OrderingTrainGroup>0</OrderingTrainGroup>
<FlagActivation/>
<FlagClosing/>
<FlagCompletion/>
<FlagSuspended/>
<WagonIntermodal>N</WagonIntermodal>
<OderIntermodal>N</OderIntermodal>
<Activation>
<ActivationRL100Location/>
<ActivationLocationLocationType/>
<ActivationUICRailAuthorityLocationNumber/>
<ActivationNetworkLocationNumber/>
<ActivationSatelliteLocationNumber/>
<ActivationFreightCarLocationNumber/>
</Activation>
<Completion>
<CompletionRL100Location/>
<CompletionLocationLocationType/>
<CompletionUICRailAuthorityLocationNumber/>
<CompletionNetworkLocationNumber/>
<CompletionSatelliteLocationNumber/>
<CompletionFreightCarLocationNumber/>
</Completion>
</Ordering>
<Ordering>
<OrderingPosition>9</OrderingPosition>
<OrderingVehicleNumber>338078493792</OrderingVehicleNumber>
<OrderingCommercialOrderKey>80201912103979328</OrderingCommercialOrderKey>
<OrderingProductionOrderKey>201912101530334318346965</OrderingProductionOrderKey>
<OrderingConsignmentNumberID/>
<OrderingTrainGroup>0</OrderingTrainGroup>
<FlagActivation/>
<FlagClosing/>
<FlagCompletion/>
<FlagSuspended/>
<WagonIntermodal>N</WagonIntermodal>
<OderIntermodal>N</OderIntermodal>
<Activation>
<ActivationRL100Location/>
<ActivationLocationLocationType/>
<ActivationUICRailAuthorityLocationNumber/>
<ActivationNetworkLocationNumber/>
<ActivationSatelliteLocationNumber/>
<ActivationFreightCarLocationNumber/>
</Activation>
<Completion>
<CompletionRL100Location/>
<CompletionLocationLocationType/>
<CompletionUICRailAuthorityLocationNumber/>
<CompletionNetworkLocationNumber/>
<CompletionSatelliteLocationNumber/>
<CompletionFreightCarLocationNumber/>
</Completion>
</Ordering>
<Ordering>
<OrderingPosition>10</OrderingPosition>
<OrderingVehicleNumber>378478296494</OrderingVehicleNumber>
<OrderingCommercialOrderKey>80201912103990982</OrderingCommercialOrderKey>
<OrderingProductionOrderKey>201912101530433292346965</OrderingProductionOrderKey>
<OrderingConsignmentNumberID/>
<OrderingTrainGroup>0</OrderingTrainGroup>
<FlagActivation/>
<FlagClosing/>
<FlagCompletion/>
<FlagSuspended/>
<WagonIntermodal>N</WagonIntermodal>
<OderIntermodal>N</OderIntermodal>
<Activation>
<ActivationRL100Location/>
<ActivationLocationLocationType/>
<ActivationUICRailAuthorityLocationNumber/>
<ActivationNetworkLocationNumber/>
<ActivationSatelliteLocationNumber/>
<ActivationFreightCarLocationNumber/>
</Activation>
<Completion>
<CompletionRL100Location/>
<CompletionLocationLocationType/>
<CompletionUICRailAuthorityLocationNumber/>
<CompletionNetworkLocationNumber/>
<CompletionSatelliteLocationNumber/>
<CompletionFreightCarLocationNumber/>
</Completion>
</Ordering>
<Ordering>
<OrderingPosition>11</OrderingPosition>
<OrderingVehicleNumber>338078414616</OrderingVehicleNumber>
<OrderingCommercialOrderKey/>
<OrderingProductionOrderKey>201912101446013616142455</OrderingProductionOrderKey>
<OrderingConsignmentNumberID/>
<OrderingTrainGroup>0</OrderingTrainGroup>
<FlagActivation/>
<FlagClosing/>
<FlagCompletion/>
<FlagSuspended/>
<WagonIntermodal>N</WagonIntermodal>
<OderIntermodal>N</OderIntermodal>
<Activation>
<ActivationRL100Location/>
<ActivationLocationLocationType/>
<ActivationUICRailAuthorityLocationNumber/>
<ActivationNetworkLocationNumber/>
<ActivationSatelliteLocationNumber/>
<ActivationFreightCarLocationNumber/>
</Activation>
<Completion>
<CompletionRL100Location/>
<CompletionLocationLocationType/>
<CompletionUICRailAuthorityLocationNumber/>
<CompletionNetworkLocationNumber/>
<CompletionSatelliteLocationNumber/>
<CompletionFreightCarLocationNumber/>
</Completion>
</Ordering>
</TransportEvent>
My XSLT tempalte is working with XML Spy Pro 2020 sp1, however with saxon 9.9 PE I get error with my accumulator in the accumulator-rule.
I know Saxon implementation is strict to W3C XSLT spec, XML Spy Pro usually not always. What did I wrong with my ``accumulator-rule`?

Since my post is too long, I have to add more text here:
And the rules for generating xml are specified in an XML file:
<?xml version='1.0' encoding='UTF-8'?>
<MessageFormat name='TransportEvent' version='2.02'>
<StructFormat name='TransportEventHeader' delimOptional='n'>
<TagField type='String' value='H0 '/>
<FieldFormat name='NotificationTriggeringOU' type='String' delimOptional='y' length='10' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='NotificationTriggeringIT' type='String' delimOptional='y' length='8' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='NotificationReference' type='String' delimOptional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='NotificationCode' type='String' delimOptional='y' length='3' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='NotificationType' type='String' delimOptional='y' length='8' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='NotificationStatus' type='String' delimOptional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='NotificationTripType' type='String' delimOptional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='ProducingRailwayUndertaking' type='String' delimOptional='y' optional='y' length='4' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='ExternalPartner' type='String' delimOptional='y' optional='y' length='35' />
<FieldFormat name='ActualNumberOfWagons' type='Numeric' delimOptional='y' optional='y' length='3' pad='0' padType='leading' trimLeading='0'/>
<FieldFormat name='ProcessingTime' type='String' delimOptional='y' length='26' pad=' ' padType='trailing' trimTrailing=' '/>
<StructFormat name='NotificationFunctionalClassification' delimOptional='y' optional='y'>
<FieldFormat name='OrderRelevant' type='String' delimOptional='y' optional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='TimetableRelevant' type='String' delimOptional='y' optional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='CapacityRelevant' type='String' delimOptional='y' optional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='IntermodalRelevant' type='String' delimOptional='y' optional='y' length='1' />
<FieldFormat name='XrailRelevant' type='String' delimOptional='y' optional='y' length='1' />
<FieldFormat name='NotificationLocationRelevant' type='String' delimOptional='y' optional='y' length='1' />
</StructFormat>
<FieldFormat name='Reserve' type='String' delimOptional='y' length='1' />
</StructFormat>
<StructFormat name='NotificationLocation' delimOptional='n' optional='y'>
<TagField type='String' value='M1 '/>
<StructFormat name='CurrentLocation' delimOptional='y' optional='y'>
<FieldFormat name='CurrentLocationRL100' type='String' delimOptional='y' optional='y' length='5' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='CurrentLocationLocationType' type='String' delimOptional='y' optional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='CurrentUICRailAuthorityNumber' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='CurrentNetworkLocationNumber' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='CurrentLocationSatelliteNumber' type='String' delimOptional='y' optional='y' length='2' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='CurrentFreightCarLocationNumber' type='String' delimOptional='y' optional='y' length='4' pad=' ' padType='trailing' trimTrailing=' '/>
</StructFormat>
<StructFormat name='NextLocation' delimOptional='y' optional='y'>
<FieldFormat name='NextLocationRL100' type='String' delimOptional='y' optional='y' length='5' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='NextLocationLocationType' type='String' delimOptional='y' optional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='NextUICRailAuthorityNumber' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='NextNetworkLocationNumber' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='NextLocationSatelliteNumber' type='String' delimOptional='y' optional='y' length='2' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='NextFreightCarLocationNumber' type='String' delimOptional='y' optional='y' length='4' pad=' ' padType='trailing' trimTrailing=' '/>
</StructFormat>
</StructFormat>
<StructFormat name='NotificationTime' delimOptional='n'>
<TagField type='String' value='M2 '/>
<FieldFormat name='ActualTime' type='String' delimOptional='y' length='18' pad=' ' padType='trailing' trimTrailing=' '/>
</StructFormat>
<StructFormat name='Trip' delimOptional='n' optional='y'>
<TagField type='String' value='Z1 '/>
<FieldFormat name='TripNumber' type='String' delimOptional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='RegionDBNetz' type='String' delimOptional='y' optional='y' length='2' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='NationalProductionDate' type='String' delimOptional='y' optional='y' length='10' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='TrainTypeMainNumber' type='String' delimOptional='y' optional='y' length='2' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='TrainTypeSubNumber' type='String' delimOptional='y' optional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='DepartureStationRL100' type='String' delimOptional='y' optional='y' length='5' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='DepartureStationUICRailAuthority' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='DepartureStationNetworkLocation' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='TargetTime' type='String' delimOptional='y' optional='y' length='18' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='RelativeTime' type='String' delimOptional='y' optional='y' length='5' pad='0' padType='leading' trimTrailing=' '/>
</StructFormat>
<StructFormat name='HandoverTakeover' delimOptional='n' optional='y'>
<TagField type='String' value='U1 '/>
<FieldFormat name='HandoverTakeoverFlag' type='String' delimOptional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='ConsigningRU' type='String' delimOptional='y' length='4' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='AcceptingRU' type='String' delimOptional='y' length='4' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='UICBorderCode' type='String' delimOptional='y' optional='y' length='3' pad=' ' padType='trailing' trimTrailing=' '/>
</StructFormat>
<StructFormat name='Ordering' delimOptional='n' optional='y' repeat='*'>
<TagField type='String' value='R1 '/>
<FieldFormat name='OrderingPosition' type='Numeric' delimOptional='y' optional='y' length='3' pad='0' padType='leading' trimLeading='0'/>
<FieldFormat name='OrderingVehicleNumber' type='String' delimOptional='y' optional='y' length='12' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='OrderingCommercialOrderKey' type='String' delimOptional='y' optional='y' length='17' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='OrderingProductionOrderKey' type='String' delimOptional='y' optional='y' length='24' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='OrderingConsignmentNumberID' type='String' delimOptional='y' optional='y' length='35' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='OrderingTrainGroup' type='Numeric' delimOptional='y' optional='y' length='3' pad='0' padType='leading' trimLeading='0'/>
<FieldFormat name='FlagActivation' type='String' delimOptional='y' optional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='FlagClosing' type='String' delimOptional='y' optional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='FlagCompletion' type='String' delimOptional='y' optional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='FlagSuspended' type='String' delimOptional='y' optional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='WagonIntermodal' type='String' delimOptional='y' optional='y' length='1' />
<FieldFormat name='OderIntermodal' type='String' delimOptional='y' optional='y' length='1' />
<StructFormat name='Activation' delimOptional='y' optional='y'>
<FieldFormat name='ActivationRL100Location' type='String' delimOptional='y' optional='y' length='5' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='ActivationLocationLocationType' type='String' delimOptional='y' optional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='ActivationUICRailAuthorityLocationNumber' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='ActivationNetworkLocationNumber' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='ActivationSatelliteLocationNumber' type='String' delimOptional='y' optional='y' length='2' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='ActivationFreightCarLocationNumber' type='String' delimOptional='y' optional='y' length='4' pad=' ' padType='trailing' trimTrailing=' '/>
</StructFormat>
<StructFormat name='Completion' delimOptional='y' optional='y'>
<FieldFormat name='CompletionRL100Location' type='String' delimOptional='y' optional='y' length='5' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='CompletionLocationLocationType' type='String' delimOptional='y' optional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='CompletionUICRailAuthorityLocationNumber' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='CompletionNetworkLocationNumber' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='CompletionSatelliteLocationNumber' type='String' delimOptional='y' optional='y' length='2' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='CompletionFreightCarLocationNumber' type='String' delimOptional='y' optional='y' length='4' pad=' ' padType='trailing' trimTrailing=' '/>
</StructFormat>
</StructFormat>
<StructFormat name='Vehicle' delimOptional='n' optional='y' repeat='*'>
<TagField type='String' value='F1 '/>
<FieldFormat name='VehicleNumber' type='String' delimOptional='y' length='12' pad=' ' padType='trailing' trimTrailing=' '/>
<StructFormat name='Damage' delimOptional='y' optional='y'>
<FieldFormat name='CapabilityCode' type='String' delimOptional='y' optional='y' length='1' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='HighDemandFromDate' type='String' delimOptional='y' optional='y' length='10' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='LastCarInspectorTime' type='String' delimOptional='y' optional='y' length='18' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='DamageTypeCode' type='String' delimOptional='y' optional='y' length='3' repeat='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='DamageCauseCode' type='String' delimOptional='y' optional='y' length='1' repeat='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='DamageDeploymentConstraint' type='String' delimOptional='y' optional='y' length='2' repeat='3' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='DamageMaxSpeed' type='Numeric' delimOptional='y' optional='y' length='3' pad='0' padType='leading' trimLeading='0'/>
</StructFormat>
</StructFormat>
<StructFormat name='Order' delimOptional='n' optional='y' repeat='*'>
<TagField type='String' value='A1 '/>
<FieldFormat name='VehicleNumber' type='String' delimOptional='y' length='12' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='CommercialOrderKey' type='String' delimOptional='y' optional='y' length='17' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='ProductionOrderKey' type='String' delimOptional='y' optional='y' length='24' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='ConsignmentNumberID' type='String' delimOptional='y' optional='y' length='35' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='OrderEntrySystem' type='String' delimOptional='y' optional='y' length='3' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='TransportType' type='String' delimOptional='y' optional='y' length='2' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='DispatchDate' type='String' delimOptional='y' optional='y' length='10' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='DispatchNumber' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='DestinationDispatchUICRailAuthorityNumber' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='DestinationDispatchLocationNumber' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='DestinationReceptionUICRailAuthorityNumber' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='DestinationReceptionLocationNumber' type='String' delimOptional='y' optional='y' length='6' pad=' ' padType='trailing' trimTrailing=' '/>
<FieldFormat name='FreightNetLoad' type='Numeric' delimOptional='y' optional='y' length='6' pad='0' padType='leading' trimLeading='0'/>
</StructFormat>
</MessageFormat>
Here is my XSLT template.
<?xml version="1.0" encoding="UTF-8"?>
<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:csb="http://www.dbcargo.org/csb" xmlns:map="http://www.w3.org/2005/xpath-functions/map" exclude-result-prefixes="#all" version="3.0">
<xsl:param name="msg" as="xs:string">H0 EVU_DBSRD PVG Z24 ABF-RF IR 0112019-12-10-14.46.18.553122NJJNNJNM1 80142455360001 M2 10.12.201914:40:00Z1 RABWR1 10.12.2019 10.12.201914:40:00 0000R1 00133807843874880201912103988789201912101530419325346965 000 NN R1 002338078480716 201912101446013716142455 000 NN R1 00324714370125580201912103961427201912101200186865346965 000 NN R1 00433807840438580201912103984329201912101530381256346965 000 NN R1 00524714273013180201912093997400201912090900494682346965 000 NN R1 00637847829609880201912104006488201912101530572232346965 000 NN R1 00737807836474280201912103954824201912101530128369346965 000 NN R1 008338079134858 201912101446013858142455 000 NN R1 00933807849379280201912103979328201912101530334318346965 000 NN R1 01037847829649480201912103990982201912101530433292346965 000 NN R1 011338078414616 201912101446013616142455 000 NN </xsl:param>
<xsl:param name="relatviePath2MFL" as="xs:string" select="'./rules.xml'"/>
<xsl:variable name="MFL" select="document($relatviePath2MFL)"/>
<xsl:output method="xml" indent="yes"/>
<xsl:mode name="unroll" on-no-match="shallow-copy" use-accumulators="position-count"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="minimalBeginOfRepeatGroup" as="xs:integer" select="fn:string-length($msg) - sum(/MessageFormat/StructFormat[not(#optional='y')]//FieldFormat/#length) + string-length( string-join(/MessageFormat/StructFormat[not(#optional='y')]//TagField/#value))"/>
<xsl:variable name="groupsize" as="map(xs:string, xs:integer)">
<xsl:map>
<xsl:for-each select="/MessageFormat/StructFormat">
<xsl:choose>
<!-- there are FieldFormat with repeat attribute -->
<xsl:when test=".//FieldFormat[#repeat]">
<xsl:variable name="sum1" select="xs:integer( sum(.//FieldFormat[not(#repeat)]/#length))"/>
<xsl:variable name="sum2" select="xs:integer( sum(for-each(.//FieldFormat[#repeat], function ($arg) as xs:integer {xs:integer($arg/#length) * xs:integer($arg/#repeat)})))"/>
<xsl:map-entry key="string(./#name)">
<xsl:sequence select="xs:integer( $sum1 + $sum2 + string-length(./TagField/#value))"/>
</xsl:map-entry>
</xsl:when>
<xsl:otherwise>
<xsl:map-entry key="string(./#name)">
<xsl:sequence select="xs:integer( sum(.//FieldFormat/#length)) + string-length(./TagField/#value)"/>
</xsl:map-entry>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:map>
</xsl:variable>
<xsl:accumulator name="position-count" as="xs:integer?" initial-value="1" streamable="no">
<xsl:accumulator-rule match="$MFL/MessageFormat/StructFormat" phase="end">
<xsl:choose>
<xsl:when test="./#repeat = '*' ">
<xsl:choose>
<xsl:when test="substring($msg, $value, string-length(./TagField/#value)) != ./TagField/#value">
<xsl:sequence select="$value"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="repeat" select="count(tokenize(fn:substring($msg, $value) , ./TagField/#value)) - 1"/>
<xsl:sequence select="$value + map:get($groupsize, ./#name) * $repeat"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="substring($msg, $value, string-length(./TagField/#value)) = ./TagField/#value">
<xsl:sequence select="$value + map:get($groupsize, string(./#name))"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:accumulator-rule>
</xsl:accumulator>
<xsl:template match="StructFormat[#repeat]" mode="unroll">
<xsl:variable name="this" select="."/>
<xsl:choose>
<xsl:when test="$this/#repeat != '*' ">
<xsl:for-each select="1 to #repeat">
<xsl:choose>
<xsl:when test="$this/#delimOptional = 'n' and $this/TagField and contains($msg, $this/TagField)">
<xsl:copy select="$this">
<xsl:apply-templates select="#* except #repeat, node()" mode="#current"/>
</xsl:copy>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="groupMsg" select="fn:substring($msg, fn:accumulator-before('position-count'), fn:accumulator-after('position-count'))"/>
<xsl:variable name="repeat" select="count(tokenize($groupMsg, $this/TagField/#value)) - 1"/>
<xsl:comment select="$repeat"/>
<xsl:for-each select="1 to $repeat">
<xsl:copy select="$this">
<xsl:apply-templates select="#* except #repeat, node()" mode="#current"/>
</xsl:copy>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="$MFL/MessageFormat/StructFormat[not(#repeat) and TagField]" mode="unroll">
<xsl:variable name="this" select="."/>
<xsl:choose>
<xsl:when test="fn:accumulator-before('position-count') = fn:accumulator-after('position-count')"/>
<xsl:otherwise>
<xsl:copy select="$this">
<xsl:apply-templates select="#* except #repeat, node()" mode="#current"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="FieldFormat[#repeat]" mode="unroll">
<xsl:variable name="this" select="."/>
<xsl:for-each select="1 to #repeat">
<xsl:copy select="$this">
<xsl:apply-templates select="#* except #repeat, node()" mode="#current"/>
</xsl:copy>
</xsl:for-each>
</xsl:template>
<xsl:variable name="complete-struct">
<xsl:apply-templates select="$MFL/*" mode="unroll"/>
</xsl:variable>
<xsl:template match="/">
<xsl:variable name="group">
<output>
<xsl:for-each select="$MFL/MessageFormat/StructFormat">
<xsl:if test="fn:accumulator-before('position-count') != fn:accumulator-after('position-count')">
<xsl:element name="{./#name}">
<xsl:attribute name="start" select="fn:accumulator-before('position-count')"/>
<xsl:attribute name="length" select="fn:accumulator-after('position-count')-1"/>
</xsl:element>
</xsl:if>
</xsl:for-each>
</output>
</xsl:variable>
<xsl:element name="{$MFL/MessageFormat/#name}">
<xsl:apply-templates select="$complete-struct/*"/>
</xsl:element>
</xsl:template>
<xsl:template match="StructFormat">
<xsl:element name="{#name}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="FieldFormat">
<xsl:variable name="precedingFieldFormatsLength" select="sum(preceding::FieldFormat/#length)"/>
<xsl:variable name="offset">
<xsl:value-of select="string-length(string-join(./preceding::TagField/#value, ''))"/>
</xsl:variable>
<xsl:element name="{#name}">
<xsl:variable name="value" select="substring($msg, 1 + $precedingFieldFormatsLength + $offset, #length)"/>
<xsl:value-of select="csb:formatField(.,$value)"/>
</xsl:element>
</xsl:template>
<!-- format output -->
<xsl:function name="csb:formatField" as="xs:string">
<xsl:param name="field" as="element()"/>
<xsl:param name="value" as="xs:string"/>
<xsl:choose>
<xsl:when test="$field/#length = '1' and $value = ' '">
<xsl:value-of select="''"/>
</xsl:when>
<!-- remove leading and trailing space -->
<xsl:when test="$field/#trimLeading = ' ' and $field/#trimTrailing = ' '">
<xsl:value-of select="fn:replace($value, '^\s+|\s+$', '')"/>
</xsl:when>
<!-- remove ONLY leading space -->
<xsl:when test="$field/#trimLeading = ' ' and fn:not(fn:exists($field//#trimTrailing))">
<xsl:value-of select="fn:replace($value, '^\s+', '')"/>
</xsl:when>
<!-- remove ONLY trailing space -->
<xsl:when test="$field/#trimTrailing = ' ' and fn:not(fn:exists($field//#trimLeading))">
<xsl:value-of select="fn:replace($value, '\s+$', '')"/>
</xsl:when>
<!-- remove leading 0 -->
<xsl:when test="$field/#type = 'Numeric' and $field/#trimLeading = '0' and fn:not(fn:exists($field//#trimTrailing))">
<!-- <xsl:value-of select="fn:replace($value, '^0+', '')"/> -->
<xsl:if test="number($value) != number($value)">
<!-- validate data -->
<xsl:message terminate="yes">
<xsl:value-of select="concat('Transformation failed. The field', $field, ' has invalid value')"/>
</xsl:message>
</xsl:if>
<xsl:value-of select="number($value)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
</xsl:stylesheet>

Related

boost::split pushes an empty string to the vector even with token_compress_on

When the input string is blank, boost::split returns a vector with one empty string in it.
Is it possible to have boost::split return an empty vector instead?
MCVE:
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>
int main() {
std::vector<std::string> result;
boost::split(result, "", boost::is_any_of(","), boost::algorithm::token_compress_on);
std::cout << result.size();
}
Output:
1
Desired output:
0
Compression compresses adjacent delimiters, it does not avoid empty tokens.
If you consider the following, you can see why this works consistently:
Live On Coliru
#include <boost/algorithm/string.hpp>
#include <string>
#include <iostream>
#include <iomanip>
#include <vector>
int main() {
for (std::string const& test : {
"", "token",
",", "token,", ",token",
",,", ",token,", ",,token", "token,,"
})
{
std::vector<std::string> result;
boost::split(result, test, boost::is_any_of(","), boost::algorithm::token_compress_on);
std::cout << "\n=== TEST: " << std::left << std::setw(8) << test << " === ";
for (auto& tok : result)
std::cout << std::quoted(tok, '\'') << " ";
}
}
Prints
=== TEST: === ''
=== TEST: token === 'token'
=== TEST: , === '' ''
=== TEST: token, === 'token' ''
=== TEST: ,token === '' 'token'
=== TEST: ,, === '' ''
=== TEST: ,token, === '' 'token' ''
=== TEST: ,,token === '' 'token'
=== TEST: token,, === 'token' ''
So, you might fix it by trimming delimiters from front and end and checking that the remaining input is non-empty:
Live On Coliru
#include <boost/algorithm/string.hpp>
#include <boost/utility/string_view.hpp>
#include <string>
#include <iostream>
#include <iomanip>
#include <vector>
int main() {
auto const delim = boost::is_any_of(",");
for (std::string test : {
"", "token",
",", "token,", ",token",
",,", ",token,", ",,token", "token,,"
})
{
std::cout << "\n=== TEST: " << std::left << std::setw(8) << test << " === ";
std::vector<std::string> result;
boost::trim_if(test, delim);
if (!test.empty())
boost::split(result, test, delim, boost::algorithm::token_compress_on);
for (auto& tok : result)
std::cout << std::quoted(tok, '\'') << " ";
}
}
Printing:
=== TEST: ===
=== TEST: token === 'token'
=== TEST: , ===
=== TEST: token, === 'token'
=== TEST: ,token === 'token'
=== TEST: ,, ===
=== TEST: ,token, === 'token'
=== TEST: ,,token === 'token'
=== TEST: token,, === 'token'
BONUS: Boost Spirit
Using Spirit X3, seems to me to be more flexible and potentially more efficient:
Live On Coliru
#include <boost/spirit/home/x3.hpp>
#include <string>
#include <iostream>
#include <iomanip>
#include <vector>
int main() {
static auto const delim = boost::spirit::x3::char_(",");
for (std::string test : {
"", "token",
",", "token,", ",token",
",,", ",token,", ",,token", "token,,"
})
{
std::cout << "\n=== TEST: " << std::left << std::setw(8) << test << " === ";
std::vector<std::string> result;
parse(test.begin(), test.end(), -(+~delim) % delim, result);
for (auto& tok : result)
std::cout << std::quoted(tok, '\'') << " ";
}
}

AES/CFB Cipher mode decrypting from the string fail

Seems like I misunderstand how is CFB cipher mode works. This leads to an error. Approaches 1 and 2 do not work because I am reading encrypted text from a created string. But approach 3 works because it gets crypted text from c string just encrypted. Can't figure it out why?
Code:
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include "modes.h"
#include "aes.h"
#include "filters.h"
using namespace std;
using namespace CryptoPP;
int main()
{
byte key[AES::DEFAULT_KEYLENGTH] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6' };
byte iv[AES::BLOCKSIZE] = { '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8' };
string data = "fur fur fur fur fur";
cout << "1: Original text: " << data << endl;
CFB_Mode<AES>::Encryption cfbEncryption(key, sizeof(key), iv);
const char* data_c_str = data.c_str();
cfbEncryption.ProcessData((byte*)data_c_str, (byte*)data_c_str, data.length() + 1);
cout << "2: Encrypted text: " << data_c_str << endl;
string d(data_c_str); // after assigning c str to a string. Can get it to work!
const char* data_c_str2 = d.c_str(); // get c str. Now the value of it the same as data_c_str.
// Approach 1 Failure
string decr;
CFB_Mode<AES>::Decryption cfbDecryption(key, sizeof(key), iv);
StreamTransformationFilter stfDecryptor(cfbDecryption, new StringSink(decr));
stfDecryptor.Put(reinterpret_cast<const unsigned char*>(data_c_str2), d.size() + 1);
stfDecryptor.MessageEnd();
cout << "3. Approach 1.: Decrypted text: " << decr << endl; // output "fur fur fur fur"
// Approach 2 Failure
CFB_Mode<AES>::Decryption cfbDecryption2(key, sizeof(key), iv);
cfbDecryption2.ProcessData((byte*)data_c_str2, (byte*)data_c_str2, data.length() + 1);
cout << "4. Approach 2.: Decrypted text: " << data_c_str2 << endl; // output "fur fur fur furЂuФX"
// Approach 3 Success. Note that below code works properly because of usage data_c_str taken from data after encryption.
CFB_Mode<AES>::Decryption cfbDecryption3(key, sizeof(key), iv);
cfbDecryption3.ProcessData((byte*)data_c_str, (byte*)data_c_str, data.length() + 1);
cout << "5. Approach 3.: Decrypted text: " << data_c_str << endl; // output "fur fur fur fur fur"
cin.get();
return 0;
}
I figured it out.
auto dl = data.length();
auto dl2 = d.length();
cout << "Encrypted data length: " << dl << endl; // output: 19
cout << "Encrypted data length at assigned string: " << dl2 << endl; // output: 14
The length of encrypted string and newly assigned string are not the same because the encrypted text contains '\0' char at 14th byte of an array.

QXmlStreamReader reads empty text, document is for sure not empty

I'm using QXmlStreamReader and QXmlStreamWriter to read and write XML files in my application.
My example XML file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Senders>
<Sender>
<Name>COMPANY XYZ</Name>
<Street>Random</Street>
<BuildingNumber>23D</BuildingNumber>
<LocalNumber>123</LocalNumber>
<CityCode>3434-21</CityCode>
<City>New York</City>
</Sender>
</Senders>
It was written with my code. Basically, I do not have problem with writing XML files but have some troubles trying to read them after writing. Here's my code, which prints out empty values (XML file is not empty).
#include "mainwindow.h"
#include <QApplication>
#include <QtCore>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFile file("../data.xml");
if(file.open(QIODevice::WriteOnly | QIODevice::Text))
{
QXmlStreamWriter xmlWriter(&file);
xmlWriter.setAutoFormatting(true);
xmlWriter.writeStartDocument();
xmlWriter.writeStartElement("Senders");
xmlWriter.writeStartElement("Sender");
xmlWriter.writeTextElement("Name", "COMPANY XYZ");
xmlWriter.writeTextElement("Street", "Random");
xmlWriter.writeTextElement("BuildingNumber", "23D");
xmlWriter.writeTextElement("LocalNumber", "123");
xmlWriter.writeTextElement("CityCode", "3434-21");
xmlWriter.writeTextElement("City", "New York");
xmlWriter.writeEndElement();
xmlWriter.writeEndElement();
file.close();
}
QVector<QString> data;
if(file.open(QIODevice::ReadOnly | QIODevice::Text))
{
QXmlStreamReader xmlReader(&file);
while (!xmlReader.atEnd() && !xmlReader.hasError())
{
xmlReader.readNext();
if (xmlReader.isStartElement())
{
qDebug() << "element name: '" << xmlReader.name().toString() << "'"
<< ", text: '" << xmlReader.text().toString() << "'" << endl;
}
}
file.close();
}
return a.exec();
}
So what I'm doing wrong while reading my file?
The output I got:
element name: ' "Senders" ' , text: ' "" '
element name: ' "Sender" ' , text: ' "" '
element name: ' "Name" ' , text: ' "" '
element name: ' "Street" ' , text: ' "" '
element name: ' "BuildingNumber" ' , text: ' "" '
element name: ' "LocalNumber" ' , text: ' "" '
element name: ' "CityCode" ' , text: ' "" '
element name: ' "City" ' , text: ' "" '
When you are at StartElement token, you can only get this element's name, not it's value. You need to read further and get to Characters token to be able to read the element's value. You would also want to skip whitespace-only tokens:
while (!xmlReader.atEnd() && !xmlReader.hasError())
{
xmlReader.readNext();
//here we are at StartElement, so we can read the element's name
if (xmlReader.isStartElement())
{
qDebug() << "element name: '" << xmlReader.name().toString() << "'";
}
//here we are inside the element, so if it is not empty, we can read the element's value
else if(xmlReader.isCharacters() && !xmlReader.isWhitespace())
{
qDebug() << "element value: '" <<xmlReader.text().toString() << "'";
}
}

Getting full xml of a node, while iterating through a boost::property_tree

I have a problem getting full xml text of boost::property_tree while iterating using BOOST_FOREACH.
Xml file is something like this:
<foo>
<bar param1="val1" param2="val2">
<one>some text</one>
<two>some text</two>
</bar>
<bar param1="val3" param2="val4">
<one>some text</one>
<two>some text</two>
</bar>
</foo>
The code I use to iterate through is next:
ptree pt;
read_xml(input_stream, pt);
BOOST_FOREACH(ptree::value_type const& bar, pt.get_child("foo"))
{
std::ostringstream oss;
write_xml(oss, bar.second);
std::cout << oss.str();
}
As output I receive (for each <bar>):
<?xml version="1.0" encoding="utf-8"?>
<one>some text</one>
<two>some text</two>
Question is, how can i receive full xml text of the <bar> tag, using above loop?
For example:
<?xml version="1.0" encoding="utf-8"?>
<bar param1="val1" param2="val2">
<one>some text</one>
<two>some text</two>
</bar>
Thanks in advance!
EDIT : added ready to copy & past piece of code
#include <sstream>
#include <iostream>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/foreach.hpp>
const std::string xml_str =
"<foo>"
"<bar param1=\"val1\" param2=\"val2\">"
"<one>some text</one>"
"<two>some text</two>"
"</bar>"
"<bar param1=\"val3\" param2=\"val4\">"
"<one>more text</one>"
"<two>more text</two>"
"</bar>"
"</foo>";
int main()
{
using namespace boost::property_tree;
using namespace boost::property_tree::xml_parser;
std::istringstream iss(xml_str);
ptree pt;
read_xml(iss, pt);
BOOST_FOREACH(ptree::value_type const& bar, pt.get_child("foo"))
{
std::ostringstream oss;
write_xml(oss, bar.second);
std::cout << oss.str() << std::endl;
}
return 0;
}

Using vertex_name when reading a GraphML file with Boost Graph

I am trying to load a simple GraphML file such that each vertex has a vertex name as stored in the GraphML. I can change the GraphML, the important thing is that I have access to the vertex_name from code afterwards.
Here's the most minimal example that I could extract that still shows the problem:
#include <iostream>
#include <string>
#include <fstream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphml.hpp>
int main()
{
using namespace boost;
typedef adjacency_list<vecS, vecS, directedS,property<vertex_name_t,std::string> > BoostGraphType;
typedef dynamic_properties BoostDynamicProperties;
std::string fn = "simple.graphml";
std::ifstream is(fn.c_str());
if (!is.is_open())
{
std::cout << "loading file '" << fn << "'failed." << std::endl;
throw "Could not load file.";
}
BoostGraphType g;
BoostDynamicProperties dp ;
const std::string vn = "vertex_name";
dp.property(vn,get(vertex_name,g));
read_graphml(is, g, dp);
for (auto vp = vertices(g); vp.first != vp.second; ++vp.first)
{
std::cout << "index '" << get(vertex_index,g,*vp.first) << "' ";
std::cout << "name '" << get(vertex_name,g,*vp.first) << "'"
<< std::endl;
}
return 0;
}
I am using the the following GraphML test file:
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="d0" for="node" attr.name="vertex_name" attr.type="string"/>
<graph id="G" edgedefault="directed">
<node id="A"> <data key="d0">A</data> </node>
<node id="B"> <data key="d0">B</data> </node>
<edge id="0" source="A" target="B"/>
</graph>
</graphml>
read_graphml throws an exception with the helpful message (e.what()):
parse error: unrecognized type "
It seems the problem is related to the vertex_name association (which I got from a comment to a previous question of mine).
If I remove
<data key="d0">A</data>
from the node, it works.
However, I need to be able to identify the vertices by vertex_name.
How can I fix this so it properly parses the graphml and does not throw? What am I doing wrong?
Your code works perfectly when I run it.
>wilbert.exe
index '0' name 'A'
index '1' name 'B'
This is using boost v1.52 on windows 7