Compare the different line item fields and map the value which is in the same xml using xslt2.0 - xslt-2.0

below one is the XML input,
<?xml version="1.0" encoding="utf-8"?>
<GSK_Canonical_MESGX2>
<header SEGMENT="1">
<orderNumber>002001454979</orderNumber>
<batchNumber>0000617944</batchNumber>
<BOM SEGMENT="1">
<operationNumber>0030</operationNumber>
<phaseIndicator>0011</phaseIndicator>
</BOM>
<BOM SEGMENT="1">
<operationNumber>0040</operationNumber>
<phaseIndicator>0012</phaseIndicator>
</BOM>
<recipe SEGMENT="1">
<phase>0011</phase>
<parentOperation>0030</parentOperation>
<workcenter>MANUOHD1</workcenter>
</recipe>
<recipe SEGMENT="1">
<phase>0012</phase>
<parentOperation>0040</parentOperation>
<workcenter>COSTOHD1</workcenter>
</recipe>
</header>
</GSK_Canonical_MESGX2>
I have an below xslt,
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" xmlns:set="http://exslt.org/sets" xmlns:str="http://exslt.org/strings" xmlns:java="http://xml.apache.org/xslt/java" xmlns:saxon="http://saxon.sf.net/" exclude-result-prefixes="exsl set str java saxon">
<xsl:output method="text"/>
<xsl:variable name="VarHash" select="'#'"/>
<xsl:variable name="VarBreak" select="'
'"/>
<xsl:variable name="pipeFieldDelimiter" select="'\|'"/>
<xsl:template match="/">
<xsl:text>HEADER</xsl:text>
<xsl:value-of select="$VarHash"/>
<xsl:value-of select="GSK_Canonical_MESGX2/header/orderNumber"/>
<xsl:value-of select="$VarHash"/>
<xsl:value-of select="GSK_Canonical_MESGX2/header/batchNumber"/>
<xsl:value-of select="$VarBreak"/>
<xsl:for-each select="GSK_Canonical_MESGX2/header/BOM">
<!--GSK_Canonical_MESGX2/Header/BOM/OperationNumber = GSK_Canonical_MESGX2/header/recipe/parentOperation and GSK_Canonical_MESGX2/Header/BOM/phaseIndicator = GSK_Canonical_MESGX2/header/recipe/phase then <xsl:value-of select="GSK_Canonical_MESGX2/header/recipe/workcenter"/> This needs to be implemented for each line item of BOM tag -->
<xsl:if test="position() != last()">
<xsl:value-of select="$VarBreak"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
below one is the expected output,
HEADER#002001454979#0000617944
MANUOHD1
COSTOHD1
now need to implement for each BOM line item,we need to compare BOM with Recipe tags and select workcenter value if the condition satisfied.
Header/BOM/OperationNumber = header/recipe/parentOperation
and
Header/BOM/phaseIndicator = header/recipe/phase
then
<xsl:value-of select="GSK_Canonical_MESGX2/header/recipe/workcenter"/>
Please help me to achieve this.Thanks

This transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kBomByPhaseAndOperation" match="BOM"
use="concat(operationNumber, '|', phaseIndicator)"/>
<xsl:template match=
"recipe[key('kBomByPhaseAndOperation',
concat(parentOperation, '|', phase))
]">
<xsl:value-of select="concat('
', workcenter)"/>
</xsl:template>
<xsl:template match="header">
<xsl:text>HEADER</xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="orderNumber|batchNumber">
<xsl:value-of select="concat('#', .)"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
When applied on the provided source XML document:
<GSK_Canonical_MESGX2>
<header SEGMENT="1">
<orderNumber>002001454979</orderNumber>
<batchNumber>0000617944</batchNumber>
<BOM SEGMENT="1">
<operationNumber>0030</operationNumber>
<phaseIndicator>0011</phaseIndicator>
</BOM>
<BOM SEGMENT="1">
<operationNumber>0040</operationNumber>
<phaseIndicator>0012</phaseIndicator>
</BOM>
<recipe SEGMENT="1">
<phase>0011</phase>
<parentOperation>0030</parentOperation>
<workcenter>MANUOHD1</workcenter>
</recipe>
<recipe SEGMENT="1">
<phase>0012</phase>
<parentOperation>0040</parentOperation>
<workcenter>COSTOHD1</workcenter>
</recipe>
</header>
</GSK_Canonical_MESGX2>
produces exactly the wanted, correct result:
HEADER#002001454979#0000617944
MANUOHD1
COSTOHD1

Related

How to access variable defined under for-each loop/If condition in another for each loop

I have to generate the output in sequence and so I wanted to know how to access the variable defined under For-each loop/If condition and then value of select inside another for loop.
As per my example how to access partn and date3? Please help and suggest.
what is the concept for achieving the same..I have tried with-param as well, but didn't work for me.
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:func="myfunc"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions" >
<xsl:output method="text" encoding="utf-8" />
<xsl:output omit-xml-declaration="yes" />
<xsl:param name="break" select="'
'" />
<xsl:template match="ZGS/ID">
<xsl:for-each select="E1">
<xsl:if test="PA = 'CE'">
<xsl:variable name="partn" select="PAN"/>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="E13">
<xsl:if test="ID = 033">
<xsl:variable name="date3"
select="substring(DAT,3,8)"/>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="E1E">
<xsl:text>823</xsl:text>
<xsl:text>03</xsl:text>
<xsl:for-each select="E1ED">
<xsl:if test="QU = 012 ">
<xsl:value-of select="BEL"/>
</xsl:if>
</xsl:for-each>
<xsl:value-of select="$partn"/>
<xsl:value-of select="$date3"/>
</xsl:for-each>
</xsl:template>
INPUT:
<?xml version='1.0' encoding='utf-8'?>
<ZGS>
<ID BEGIN="1">
<E1 SEGMENT="1">
<PA>AG</PA>
<NAME>ABC</NAME>
<SP>E</SP>
<AND>0004</AND>
</E1>
<E1 SEGMENT="1">
<PA>RE</PA>
<PAN>IUIOP</PAN>
<NAME>ABC1</NAME>
<SP>EQ</SP>
<AND>0005</AND>
<EKA3 SEGMENT="1">
<QU>009</QU>
</EKA3>
</E1>
<E1 SEGMENT="1">
<PA>CE</PA>
<PAN>PODW</PAN>
<NAME>ABC2</NAME>
<SP>EP</SP>
<AND>0006</AND>
</E1>
<E13 SEGMENT="1">
<ID>001</ID>
<DAT>20190329</DAT>
</E13>
<E13 SEGMENT="1">
<ID>002</ID>
<DAT>20190429</DAT>
</E13>
<E13 SEGMENT="1">
<IDD>033</IDD>
<DAT>20190529</DAT>
</E13>
<E1E>
<E1ED>
</E1ED>
<E1ED>
</E1ED>
</E1E>
In XSLT, variables once declared/defined, they cannot be changed. And exists only in the loop they are defined.
You might not need the xsl:for-each loop here. Instead the variables can be globally defined, so that you can use them where you want in your xslt.
You can try the following:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:func="myfunc"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="text" encoding="utf-8" />
<xsl:output omit-xml-declaration="yes" />
<xsl:param name="break" select="'
'" />
<xsl:variable name="partn" select="/ZGS/ID/E1[PA = 'CE']/PAN" />
<xsl:variable name="date3" select="substring(/ZGS/ID/E13[ID = '033']/DAT,3,8)" />
<xsl:template match="ZGS/ID">
<xsl:for-each select="E1E">
<xsl:text>823</xsl:text>
<xsl:text>03</xsl:text>
<xsl:for-each select="E1ED">
<xsl:if test="QU = 012 ">
<xsl:value-of select="BEL" />
</xsl:if>
</xsl:for-each>
<xsl:value-of select="$partn" />
<xsl:value-of select="$date3" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/jyRYYiu
Using xsl:param, it can be achieved as
<xsl:param name="partn" select="/ZGS/ID/E1[PA = 'CE']/PAN" />
<xsl:param name="date3" select="substring(/ZGS/ID/E13[ID = '033']/DAT,3,8)" />
<xsl:template match="ZGS/ID">
<xsl:for-each select="E1E">
<xsl:text>823</xsl:text>
<xsl:text>03</xsl:text>
<xsl:for-each select="E1ED">
<xsl:if test="QU = 012 ">
<xsl:value-of select="BEL" />
</xsl:if>
</xsl:for-each>
<xsl:for-each select="$partn">
<xsl:value-of select="." />
</xsl:for-each>
<xsl:value-of select="$date3" />
</xsl:for-each>
</xsl:template>
https://xsltfiddle.liberty-development.net/jyRYYiu/1

change the xlmns value without modifying the prefix using xslt (with built in templates)

Source XML Document:
<?xml version="1.0" encoding="UTF-8"?>
<PREMIS:premis xmlns:PREMIS="info:lc/xmlns/premis-v2" version="2.2">
<PREMIS:object xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="PREMIS:file">
<PREMIS:objectIdentifier>
<PREMIS:objectIdentifierType>Docuteam</PREMIS:objectIdentifierType>
<PREMIS:objectIdentifierValue>_20161027171024801</PREMIS:objectIdentifierValue>
</PREMIS:objectIdentifier>
<PREMIS:objectCharacteristics>
<PREMIS:compositionLevel>0</PREMIS:compositionLevel>
<PREMIS:fixity>
<PREMIS:messageDigestAlgorithm>SHA-512</PREMIS:messageDigestAlgorithm>
<PREMIS:messageDigest>2b9be7ebeae4135b0002cfcd7ee4ee2f5d93e80bfabebf6d5d409e504ad1cbd920487f56726362c2a2979b68d96b1c26f37a73e68c30dd9f8cf11502c634ff5a</PREMIS:messageDigest>
</PREMIS:fixity>
<PREMIS:size>32783388</PREMIS:size>
<PREMIS:format>
<PREMIS:formatDesignation>
<PREMIS:formatName>Tagged Image File Format</PREMIS:formatName>
</PREMIS:formatDesignation>
<PREMIS:formatRegistry>
<PREMIS:formatRegistryName>PRONOM</PREMIS:formatRegistryName>
<PREMIS:formatRegistryKey>fmt/353</PREMIS:formatRegistryKey>
</PREMIS:formatRegistry>
</PREMIS:format>
</PREMIS:objectCharacteristics>
<PREMIS:originalName xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple"
>12448399.tif</PREMIS:originalName>
</PREMIS:object>
<PREMIS:event>
<PREMIS:eventIdentifier>
<PREMIS:eventIdentifierType>Docuteam</PREMIS:eventIdentifierType>
<PREMIS:eventIdentifierValue>_20161027171025082</PREMIS:eventIdentifierValue>
</PREMIS:eventIdentifier>
<PREMIS:eventType>Creation</PREMIS:eventType>
<PREMIS:eventDateTime>2016-10-27T17:10:25</PREMIS:eventDateTime>
<PREMIS:eventDetail>Performed by: &apos;INGEST-01$&apos;</PREMIS:eventDetail>
<PREMIS:eventOutcomeInformation>
<PREMIS:eventOutcome>Success</PREMIS:eventOutcome>
</PREMIS:eventOutcomeInformation>
<PREMIS:linkingObjectIdentifier xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:type="simple">
<PREMIS:linkingObjectIdentifierType>Docuteam</PREMIS:linkingObjectIdentifierType>
<PREMIS:linkingObjectIdentifierValue>_20161027171024801</PREMIS:linkingObjectIdentifierValue>
</PREMIS:linkingObjectIdentifier>
</PREMIS:event>
<PREMIS:event>
<PREMIS:eventIdentifier>
<PREMIS:eventIdentifierType>Docuteam</PREMIS:eventIdentifierType>
<PREMIS:eventIdentifierValue>_20161027171031973</PREMIS:eventIdentifierValue>
</PREMIS:eventIdentifier>
<PREMIS:eventType>Fixity Check</PREMIS:eventType>
<PREMIS:eventDateTime>2016-10-27T17:10:31</PREMIS:eventDateTime>
<PREMIS:eventDetail>Based on sa_ub-erara-01_dss-01. Performed by:
&apos;INGEST-01$&apos;</PREMIS:eventDetail>
<PREMIS:eventOutcomeInformation>
<PREMIS:eventOutcome>Success</PREMIS:eventOutcome>
</PREMIS:eventOutcomeInformation>
<PREMIS:linkingObjectIdentifier xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:type="simple">
<PREMIS:linkingObjectIdentifierType>Docuteam</PREMIS:linkingObjectIdentifierType>
<PREMIS:linkingObjectIdentifierValue>_20161027171024801</PREMIS:linkingObjectIdentifierValue>
</PREMIS:linkingObjectIdentifier>
</PREMIS:event>
</PREMIS:premis>
My XSLT:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:PREMIS="info:lc/xmlns/premis-v2"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple"
>
<xsl:output method="xml"/>
<xsl:template match="/">
<rdf:RDF>
<xsl:value-of select="'
'"/>
<xsl:value-of select="'
'"/>
<xsl:apply-templates/>
</rdf:RDF>
</xsl:template>
<xsl:template match="PREMIS:premis">
<xsl:apply-templates select="PREMIS:object"/>
<xsl:value-of select="'
'"/>
<xsl:apply-templates select="PREMIS:event"/>
<xsl:value-of select="'
'"/>
</xsl:template>
<xsl:template match="PREMIS:object">
<!-- Verknüpfung zwischen Fedora- und PREMIS-Objekt -->
<!-- Der Identifikator des Fedoraobjektes "info:fedora/CH-001898-1:X" ist nicht im PREMIS-XML gespeichert, sondern muss irgendwie extern eingefügt werden -->
<rdf:Description rdf:about="info:fedora/CH-001898-1:7">
<PREMIS:hasObject><xsl:value-of select="PREMIS:objectIdentifier/PREMIS:objectIdentifierValue"/></PREMIS:hasObject>
</rdf:Description>
<xsl:value-of select="'
'"/>
<!-- PREMIS:object -->
<!-- Ebene1 -->
<rdf:Description>
<xsl:attribute name="rdf:about">
<xsl:value-of select="PREMIS:objectIdentifier/PREMIS:objectIdentifierValue"/>
</xsl:attribute>
<PREMIS:hasIdentifier><xsl:value-of select="PREMIS:objectIdentifier/PREMIS:objectIdentifierValue"/><xsl:text>objectIdentifier</xsl:text></PREMIS:hasIdentifier>
<PREMIS:hasOriginalName><xsl:value-of select="PREMIS:originalName"/></PREMIS:hasOriginalName>
</rdf:Description>
<xsl:value-of select="'
'"/>
<!-- Ebene2 -->
<rdf:Description>
<xsl:attribute name="rdf:about">
<xsl:value-of select="PREMIS:objectIdentifier/PREMIS:objectIdentifierValue"/><xsl:text>objectIdentifier</xsl:text></xsl:attribute>
<PREMIS:hasIdentifierType><xsl:value-of select="PREMIS:objectIdentifier/PREMIS:objectIdentifierType"/></PREMIS:hasIdentifierType>
<PREMIS:hasIdentifierValue><xsl:value-of select="PREMIS:objectIdentifier/PREMIS:objectIdentifierValue"/></PREMIS:hasIdentifierValue>
</rdf:Description>
<xsl:value-of select="'
'"/>
</xsl:template>
<!-- Events -->
<!-- Ebene1 -->
<xsl:template match="PREMIS:event">
<rdf:Description>
<xsl:attribute name="rdf:about">
<xsl:value-of select="PREMIS:eventIdentifier/PREMIS:eventIdentifierValue"/></xsl:attribute>
<PREMIS:hasIdentifier><xsl:value-of select="PREMIS:eventIdentifier/PREMIS:eventIdentifierValue"/></PREMIS:hasIdentifier>
<PREMIS:EventDateTime><xsl:value-of select="PREMIS:eventDateTime"/></PREMIS:EventDateTime>
<PREMIS:EventDetail><xsl:value-of select="PREMIS:eventDetail"/></PREMIS:EventDetail>
<PREMIS:hasEventOutcomeInformation><xsl:value-of select="PREMIS:eventIdentifier/PREMIS:eventIdentifierValue"/><xsl:text>eventOutcomeInformation</xsl:text></PREMIS:hasEventOutcomeInformation>
<PREMIS:hasEventLinkingObjectIdentifier><xsl:value-of select="PREMIS:eventIdentifier/PREMIS:eventIdentifierValue"/><xsl:text>eventLinkingObjectIdentifier</xsl:text></PREMIS:hasEventLinkingObjectIdentifier>
</rdf:Description>
<xsl:value-of select="'
'"/>
<!-- Ebene2 -->
<rdf:Description>
<xsl:attribute name="rdf:about">
<xsl:value-of select="PREMIS:eventIdentifier/PREMIS:eventIdentifierValue"/><xsl:text>eventIdentifier</xsl:text></xsl:attribute>
<PREMIS:hasIdentifierType><xsl:value-of select="PREMIS:eventIdentifier/PREMIS:eventIdentifierType"/></PREMIS:hasIdentifierType>
<PREMIS:hasIdentifierValue><xsl:value-of select="PREMIS:eventIdentifier/PREMIS:eventIdentifierValue"/></PREMIS:hasIdentifierValue>
</rdf:Description>
<xsl:value-of select="'
'"/>
<rdf:Description>
<xsl:attribute name="rdf:about">
<xsl:value-of select="PREMIS:eventIdentifier/PREMIS:eventIdentifierValue"/><xsl:text>eventOutcomeInformation</xsl:text></xsl:attribute>
<PREMIS:hasEventOutcome><xsl:value-of select="PREMIS:eventOutcomeInformation/PREMIS:eventOutcome"/></PREMIS:hasEventOutcome>
</rdf:Description>
<xsl:value-of select="'
'"/>
<rdf:Description>
<xsl:attribute name="rdf:about">
<xsl:value-of select="PREMIS:eventIdentifier/PREMIS:eventIdentifierValue"/><xsl:text>eventLinkingObjectIdentifier</xsl:text></xsl:attribute>
<PREMIS:linkingObjectIdentifierType><xsl:value-of select="PREMIS:linkingObjectIdentifier/PREMIS:linkingObjectIdentifierType"/></PREMIS:linkingObjectIdentifierType>
<PREMIS:hasLinkingObjectIdentifierValue><xsl:value-of select="PREMIS:linkingObjectIdentifier/PREMIS:linkingObjectIdentifierValue"/></PREMIS:hasLinkingObjectIdentifierValue>
</rdf:Description>
<xsl:value-of select="'
'"/>
</xsl:template>
</xsl:stylesheet>
In the output xml document I want the value of xmlns:PREMIS to be changed to "http://www.loc.gov/premis/rdf/v1#". So the opening root element should look like this:
<rdf:RDF xmlns:PREMIS="info:lc/xmlns/premis-v2"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xlink="http://www.w3.org/1999/xlink">
I've tried several things, also posts I've discovered in here. But I don't get it. Any ideas? Thanks.
Post-Process XSLT:
<?xml version="1.0"?>
<!-- sample_2.xsl -->
<xsl:stylesheet version="2.0"
exclude-result-prefixes="PREMIS"
xmlns:PREMIS="info:lc/xmlns/premis-v2"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple"
>
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="namespace::* except namespace::PREMIS"/>
<xsl:namespace name="PREMIS" select="'http://www.loc.gov/premis/rdf/v1#'"/>
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="PREMIS:*">
<xsl:element name="PREMIS:{local-name()}" namespace="http://www.loc.gov/premis/rdf/v1#">
<xsl:copy-of select="namespace::* except namespace::PREMIS"/>
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template></xsl:stylesheet>
I'm assuming that your desired output is a typo, and that you actually want this:
<rdf:RDF xmlns:PREMIS="http://www.loc.gov/premis/rdf/v1#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xlink="http://www.w3.org/1999/xlink">
...
</rdf:RDF>
In your stylesheet, using the same prefix PREMIS to refer to different namespaces depending on whether you are reading or writing is going to be extremely difficult. Does the prefix in the output really have to be PREMIS, or will some other prefix do? If it does have to be the same (and perhaps anyway) I think my preferred approach would be to post-process the output using:
<xsl:stylesheet exclude-result-prefixes="PREMIS"...>
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="namespace::* except namespace::PREMIS"/>
<xsl:namespace name="PREMIS" select="'http://www.loc.gov/premis/rdf/v1#'"/>
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="PREMIS:*">
<xsl:element name="PREMIS:{local-name()}" namespace="http://www.loc.gov/premis/rdf/v1#">
<xsl:copy-of select="namespace::* except namespace::PREMIS"/>
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>

I have a source document:

I have a source document:
<?xml version = "1.0" encoding = "UTF-8"?>
<Circuit revision="B" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Block name="Design">
<Data>
<Layer name="INDEX_4" Function="PLANE"></Layer>
<Layer name="INDEX_9" Function="CORE"></Layer>
<Group name="PRIMARY">
<SubGroup name="GROUP_PRIMARY">
<SubLayer Ref="INDEX_4" thickness="0.0350"></SubLayer>
<SubLayer Ref="INDEX_9" thickness="0.1000"></SubLayer>
</SubGroup>
</Group>
</Data>
</Block>
</Circuit>
This stylesheet using current() extracts the corresponding thickness:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="/Circuit/Block/Data/Layer">
<xsl:element name="{name()}">
<xsl:attribute name="id">
<xsl:value-of select="#name"/>
</xsl:attribute>
<xsl:attribute name="Function">
<xsl:value-of select="#Function"/>
</xsl:attribute>
<xsl:value-of select="/Circuit/Block/Data/Group/SubGroup/SubLayer[#Ref=current()/#name]/#thickness"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Here's the second stylesheet to extract the PREVIOUS thickness value:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="/Circuit/Block/Data/Layer">
<xsl:element name="{name()}">
<xsl:attribute name="id">
<xsl:value-of select="#name"/>
</xsl:attribute>
<xsl:attribute name="Function">
<xsl:value-of select="#Function"/>
</xsl:attribute>
<xsl:value-of select="/Circuit/Block/Data/Group/SubGroup/SubLayer[#Ref=preceding-sibling::*[1]/#name]/#thickness"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
In both cases I get this:
<?xml version="1.0" encoding="UTF-8"?>
<Layer id="INDEX_4" Function="PLANE">0.0350</Layer>
<Layer id="INDEX_9" Function="CORE">0.1000</Layer>
I tried the preceding-sibling to get the preceding value - I guess the question is "What is the context of the preceding-sibling?"
Is it the group with the Layer element or the group with the SubLayer element?
Thanks
Ralph B
Within any predicate the context item is the selected item in the step before the predicate so with SubLayer[#Ref=preceding-sibling::*[1]/#name] the context for both #Ref as well as preceding-sibling::*[1]/#name is the SubLayer element. If you want to select relative to the currently matched Layer element in the template you need to use current()/preceding-sibling::*[1]/#name inside the predicate.

Extracting value from External xml based on some rule in xsl

This is input xml input.xml
<root>
<bodytext>
<remotelink refptid="HKBL1.0001.lohk.CAP65">some text</remotelink>
<remotelink refptid="HKBL1.0001.lohk.CAP199999">some text</remotelink>
</bodytext>
</root>
This is Prop.xml
<?xml version="1.0" encoding="utf-8"?>
<properties>
<code dpsi="0BZG" docid="asdww">HKBL1.0001.lohk.CAP65</code>
<code dpsi="0BZH" docid="navin">HKBL1.0002.aohk.CAP383</code>
<code no="3">345</code>
</properties>
This is desired output
<root>
<bodytext>
<remotelink refptid="HKBL1.0001.lohk.CAP65" dpsi="0BZG" docid="asdww">some text</remotelink>
<remotelink refptid="HKBL1.0001.lohk.CAP199999">some text</remotelink>
</bodytext>
</root>
IF prop.xml code/text matches remotelink/#refptid than copy attribute of prop.xml to remotelink otherwise no changes in remotelink.
This is the XSLT I have written. So far I am not getting result for unmatched condition:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlsx="http://www.stylusstudio.com/XSLT/XLSX" xmlns:spml="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:saxon="http://saxon.sf.net/" version="2.0">
<xsl:template match="#*|node()" name="root">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="remotelink[#service='DOC-ID']" name="t-remote">
<xsl:variable name="refptid" select="./#refpt"/>
<xsl:variable name="path" select="doc('file:/C:/Users/DalalNS/Desktop/xslt/prop.xml')"/>
<xsl:for-each select="$path/properties/code">
<xsl:choose>
<xsl:when test="./text()=$refptid">
<xsl:element name="remotelink">
<xsl:attribute name="DOC-ID" select="./#docid"/>
<xsl:attribute name="dpsi" select="./#dpsi"/>
<xsl:attribute name="refpt" select="$refptid"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:if test="./#docrefid"/>
</xsl:template>
</xsl:stylesheet>
<xsl:template match="remotelink[#service='DOC-ID']"> will never never be triggered, there's no service attribute on the <remotelink> element. Moreover, you don't retrieve the correct attribute (refpt instead of refptid)
This XSL transformation should do the job:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlsx="http://www.stylusstudio.com/XSLT/XLSX" xmlns:spml="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:saxon="http://saxon.sf.net/" version="2.0">
<xsl:variable name="props.doc" select="doc('file:/C:/Users/DalalNS/Desktop/xslt/prop.xml')/properties" />
<xsl:template match="#*|node()" name="root">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="remotelink" name="t-remote">
<xsl:variable name="refptid" select="./#refptid"/>
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:if test="$props.doc/code[. = $refptid]">
<xsl:apply-templates select="$props.doc/code[. = $refptid]/#*"/>
</xsl:if>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This is the result of the transformation:
<?xml version="1.0" encoding="UTF-8"?><root>
<bodytext>
<remotelink refptid="HKBL1.0001.lohk.CAP65" dpsi="0BZG" docid="asdww">some text</remotelink>
<remotelink refptid="HKBL1.0001.lohk.CAP199999">some text</remotelink>
</bodytext>
</root>
I would simply define a global parameter or variable <xsl:variable name="path" select="doc('file:/C:/Users/DalalNS/Desktop/xslt/prop.xml')"/>, then set up a key <xsl:key name="prop" match="code" use="."/>, and then use that in a template
<xsl:template match="remotelink[key('prop', #refptid, $path)]">
<xsl:copy>
<xsl:copy-of select="key('prop', #refptid, $path)/#*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
that, together with your first template, should suffice.

Splitfunction gives troubles

I'm facing the following problem or challenge.
I've a an element in my source XML which can have 450 characters.
With my xslt I want to transform this into chunks of 75 characters.
...
<T61>
<parentInfo>SomeInfo</parentInfo>
<T86>
<info>abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890</info>
</T86>
</T61>
...
The output I generate should look something like:
<T31>
<x>abcdefghijklmnopqrstuvwxyz01234567890</x>
</T31>
<T31>
<x>abcdefghijklmnopqrstuvwxyz01234567890</x>
</T31>
In my code I use an template for T61 which does his work.
I thought to create another template for T86 and call this from inside the T61 template but this seems not to work because I've the complete string. I created an function which could split up the string in parts of 75. But the outcome of the function is still the complete string.
I used a function from an earlier post:
<xsl:function name="my:splitItUp" as="xs:string">
<xsl:param name="input" as="xs:string"/>
<xsl:param name="chunk-size" as="xs:integer"/>
<xsl:value-of>
<xsl:for-each-group select="string-to-codepoints($input)" group-by="(position() -1) idiv $chunk-size">
<xsl:sequence select="codepoints-to-string(current-group())"/>
</xsl:for-each-group>
</xsl:value-of>
</xsl:function>
...
<xsl:template match="T86">
<xsl:for-each select="my:splitItUp(info, 75)">
<T31>
<communication>
<xsl:value-of select="." />
</communication>
</T31>
</xsl:for-each>
</xsl:template>
This structure always result in a complete string. In debug I see it split it up but it concatenates the result together. Can I somehow come out of the function?
Best Regards Dirk
Please have a look this XSLT where you need to set <xsl:param name="stringRequired" select="xs:integer(13)"/> to chunk text:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes" encoding="utf-8"/>
<xsl:param name="XML">
<info>abcdefghijklmnopqrstuvwxyz01234567890abcdefghijklmnopqrstuvwxyz01234567890</info>
</xsl:param>
<xsl:param name="stringRequired" select="xs:integer(13)"/>
<xsl:param name="XMLLenfgh" select="string-length($XML)"/>
<xsl:template match="/">
<xsl:choose>
<xsl:when test="$XMLLenfgh gt $stringRequired">
<xsl:call-template name="getPart"/>
</xsl:when>
<xsl:otherwise>
<T31>
<x>
<xsl:value-of select="$XML/info"/>
</x>
</T31>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="getPart">
<xsl:param name="XML" select="$XML"/>
<xsl:param name="stringRequired" select="$stringRequired"/>
<xsl:param name="XMLLenfgh" select="$XMLLenfgh"/>
<xsl:message>
<xsl:value-of select="$XML"/>
</xsl:message>
<xsl:if test="$XMLLenfgh gt $stringRequired">
<T>
<x>
<xsl:value-of select="substring($XML,1,$stringRequired)"/>
</x>
</T>
<xsl:call-template name="getPart">
<xsl:with-param name="XML"
select="substring($XML,string-length(substring($XML,1,$stringRequired)))"/>
<xsl:with-param name="XMLLenfgh"
select="string-length(substring($XML,string-length(substring($XML,1,$stringRequired))))"/>
<xsl:with-param name="stringRequired" select="$stringRequired"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
OUTPUT:
<T xmlns:xs="http://www.w3.org/2001/XMLSchema">
<x>abcdefghijklm</x>
</T>
<T xmlns:xs="http://www.w3.org/2001/XMLSchema">
<x>mnopqrstuvwxy</x>
</T>
<T xmlns:xs="http://www.w3.org/2001/XMLSchema">
<x>yz01234567890</x>
</T>
<T xmlns:xs="http://www.w3.org/2001/XMLSchema">
<x>0abcdefghijkl</x>
</T>
<T xmlns:xs="http://www.w3.org/2001/XMLSchema">
<x>lmnopqrstuvwx</x>
</T>
<T xmlns:xs="http://www.w3.org/2001/XMLSchema">
<x>xyz0123456789</x>
</T>

Resources