1

I tried to do XSLT transform one XML file to another XML used XSLT generated in Altova Map Force.

At first, I had the problem when saxon processor can't found Altova specific functions described here: http://manual.altova.com/stylevision/stylevisionenterprise/index.html?fxaltova_xpxqnumeric.htm

functions that used in my XSLT is "generate-auto-number" and "reset-auto-number".

The problem was "Error at xsl:variable on line 41 column 85 of AltovaXSLT.xslt: XPST0017 XPath syntax error at char 0 on line 41 near ...r('mapforce_autonumber_153336056'): Cannot find a matching 4-argument function named ://www.altova.com/xslt-extensions}reset-auto-number()"

I solve this problem by using registerExtensionFunction in saxon processor.

But, my functions called only once. In output XML a can see my generated numbers but always the same number. What i do wrong, please help?

Input XML:

<?xml version="1.0" encoding="UTF-8"?>
<Results xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="PassThrough.xsd"
         FileType="Snapshot"
         ODMVersion="1.3.2"
         dataSet="1.0.0"
         FileOID="482ea709-3e9c-46f5-86ed-1344963b81a4"
         CreationDtateTime="2015-09-28T11:51:59.548-04:00">
   <Study StudyOID="Some Study OID">
      <MetadataInfo MetadataVersionOID="v1.3.2" MetadataVersionName="Version 1.3.2"/>
      <StudyName>Some name</StudyName>
      <StudyDescription/>
      <ProtocolName>Some name</ProtocolName>
   </Study>
   <Patient StudyOID="Some study OID"
            SubjectKey="11"
            MetaDataVersionOID="v1.3.2"
            Visit="SE.week_24_arm_1">
      <Item StudyEventOID="SE.day_1_arm_1"
            FormOID="FM.subject_enrollment_form"
            ItemGroupOID="IG.subject_enrollment_form"
            ItemOID="IT.record_id"
            ItemValue="11"/>
      <Item StudyEventOID="SE.day_1_arm_1"
            FormOID="FM.demographics"
            ItemGroupOID="IG.demographics"
            ItemOID="IT.dm_sex"
            ItemValue="F"/>
      <Item StudyEventOID="SE.day_1_arm_1"
            FormOID="FM.demographics"
            ItemGroupOID="IG.demographics"
            ItemOID="IT.dm_ethnic"
            ItemValue="HISPANIC_OR_LATINO"/>
      ........
      ....
      ........
   </Patient>
</Results>

XSLT Transform:

    <?xml version="1.0" encoding="UTF-8"?>
<!--
This file was generated by Altova MapForce 2015r4sp1

YOU SHOULD NOT MODIFY THIS FILE, BECAUSE IT WILL BE
OVERWRITTEN WHEN YOU RE-RUN CODE GENERATION.

Refer to the Altova MapForce Documentation for further details.
http://www.altova.com/mapforce
-->
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:vmf="http://www.altova.com/MapForce/UDF/vmf" xmlns:ns0="http://www.altova.com/xslt-extensions" xmlns:ns1="http://www.cdisc.org/ns/odm/v1.3" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="vmf ns0 ns1 xs fn">
    <xsl:template name="vmf:vmf1_inputtoresult">
        <xsl:param name="input" select="()"/>
        <xsl:choose>
            <xsl:when test="$input='SE.week_24_arm_2'">
                <xsl:copy-of select="'WEEK 24'"/>
            </xsl:when>
            <xsl:when test="$input='SE.day_28_arm_2'">
                <xsl:copy-of select="'DAY 28'"/>
            </xsl:when>
            <xsl:when test="$input='SE.day_0_arm_2'">
                <xsl:copy-of select="'BASELINE'"/>
            </xsl:when>
            <xsl:when test="$input='SE.day_3_arm_3'">
                <xsl:copy-of select="'DAY 3'"/>
            </xsl:when>
            <xsl:when test="$input='SE.day_7_arm_3'">
                <xsl:copy-of select="'DAY 7'"/>
            </xsl:when>
            <xsl:when test="$input='SE.day_14_arm_3'">
                <xsl:copy-of select="'DAY 14'"/>
            </xsl:when>
            <xsl:when test="$input='SE.day_0_arm_3'">
                <xsl:copy-of select="'BASELINE'"/>
            </xsl:when>
        </xsl:choose>
    </xsl:template>
    <xsl:output method="xml" encoding="UTF-8" byte-order-mark="no" indent="yes"/>
    <xsl:template match="/">
        <xsl:variable name="var13_Results" as="node()?" select="Results"/>
        <xsl:sequence select="ns0:reset-auto-number('mapforce_autonumber_153336056')"/>
        <ODM xmlns="http://www.cdisc.org/ns/odm/v1.3" xmlns:data="http://www.cdisc.org/ns/Dataset-XML/v1.0">
            <xsl:for-each select="$var13_Results[fn:exists(@FileType)]">
                <xsl:attribute name="FileType" namespace="" select="fn:string(@FileType)"/>
            </xsl:for-each>
            <xsl:for-each select="$var13_Results[fn:exists(@ODMVersion)]">
                <xsl:attribute name="ODMVersion" namespace="" select="fn:string(@ODMVersion)"/>
            </xsl:for-each>
            <xsl:for-each select="$var13_Results[fn:exists(@dataSet)]">
                <xsl:attribute name="data:DatasetXMLVersion" select="fn:string(@dataSet)"/>
            </xsl:for-each>
            <xsl:for-each select="$var13_Results[fn:exists(@FileOID)]">
                <xsl:attribute name="FileOID" namespace="" select="fn:string(@FileOID)"/>
            </xsl:for-each>
            <xsl:for-each select="$var13_Results[fn:exists(@PriorFileOID)]">
                <xsl:attribute name="PriorFileOID" namespace="" select="fn:string(@PriorFileOID)"/>
            </xsl:for-each>
            <xsl:for-each select="$var13_Results[fn:exists(@Originator)]">
                <xsl:attribute name="Originator" namespace="" select="fn:string(@Originator)"/>
            </xsl:for-each>
            <xsl:for-each select="$var13_Results[fn:exists(@CreationDtateTime)]">
                <xsl:attribute name="CreationDateTime" namespace="" select="fn:string(@CreationDtateTime)"/>
            </xsl:for-each>
            <xsl:for-each select="$var13_Results">
                <xsl:variable name="var12_current" as="node()" select="."/>
                <xsl:for-each select="*:Study[fn:namespace-uri() eq '']">
                    <xsl:variable name="var11_StudyOID" as="node()?" select="@StudyOID"/>
                    <xsl:variable name="var10_resultof_exists" as="xs:boolean" select="fn:exists($var11_StudyOID)"/>
                    <ClinicalData>
                        <xsl:if test="$var10_resultof_exists">
                            <xsl:attribute name="StudyOID" namespace="" select="fn:string($var11_StudyOID)"/>
                        </xsl:if>
                        <xsl:for-each select="*:MetadataInfo[fn:namespace-uri() eq ''][fn:exists(@MetadataVersionOID)]">
                            <xsl:attribute name="MetaDataVersionOID" namespace="" select="fn:string(@MetadataVersionOID)"/>
                        </xsl:for-each>
                        <xsl:for-each select="$var12_current/*:Patient[fn:namespace-uri() eq '']">
                            <xsl:variable name="var9_resultof_cast" as="xs:string" select="fn:string(@SubjectKey)"/>
                            <xsl:variable name="var7_resultof_vmf__inputtoresult" as="xs:string?">
                                <xsl:call-template name="vmf:vmf1_inputtoresult">
                                    <xsl:with-param name="input" select="fn:string(@Visit)" as="xs:string"/>
                                </xsl:call-template>
                            </xsl:variable>
                            <xsl:variable name="var8_resultof_filter" as="node()*" select="*:Item[fn:namespace-uri() eq ''][fn:exists(@ItemOID)]"/>
                            <xsl:variable name="var6_resultof_filter" as="node()*" select="$var8_resultof_filter[(fn:string(@ItemOID) = 'IT.dm_race')]"/>
                            <xsl:variable name="var5_resultof_filter" as="node()*" select="$var6_resultof_filter[fn:exists(@ItemValue)]"/>
                            <xsl:variable name="var3_resultof_map" as="item()*">
                                <xsl:for-each select="$var5_resultof_filter">
                                    <xsl:sequence select="fn:string(@ItemValue)"/>
                                </xsl:for-each>
                            </xsl:variable>
                            <xsl:variable name="var4_resultof_equal" as="xs:boolean" select="(fn:count($var3_resultof_map) = xs:decimal('1'))"/>
                            <ItemGroupData>
                                <xsl:attribute name="ItemGroupOID" namespace="" select="'IG.DM'"/>
                                <xsl:variable name="var1_resultof_auto_number" as="xs:integer" select="ns0:generate-auto-number('mapforce_autonumber_153336056', xs:integer('1'), xs:integer('1'), '')"/>
                                <xsl:attribute name="data:ItemGroupDataSeq" select="xs:string($var1_resultof_auto_number)"/>
                                <ItemData>
                                    <xsl:attribute name="ItemOID" namespace="" select="'IT.STUDYID'"/>
                                    <xsl:if test="$var10_resultof_exists">
                                        <xsl:attribute name="Value" namespace="" select="fn:string($var11_StudyOID)"/>
                                    </xsl:if>
                                </ItemData>
                                <ItemData>
                                    <xsl:attribute name="ItemOID" namespace="" select="'IT.DM.DOMAIN'"/>
                                    <xsl:attribute name="Value" namespace="" select="'DM'"/>
                                </ItemData>
                                <ItemData>
                                    <xsl:attribute name="ItemOID" namespace="" select="'IT.USUBJID'"/>
                                    <xsl:attribute name="Value" namespace="" select="$var9_resultof_cast"/>
                                </ItemData>
                                <ItemData>
                                    <xsl:attribute name="ItemOID" namespace="" select="'IT.DM.SUBJID'"/>
                                    <xsl:attribute name="Value" namespace="" select="$var9_resultof_cast"/>
                                </ItemData>
                                <xsl:for-each select="$var8_resultof_filter[fn:starts-with(fn:string(@ItemOID), 'IT.site_name')][fn:exists(@ItemValue)]">
                                    <ItemData>
                                        <xsl:attribute name="ItemOID" namespace="" select="'IT.DM.SITEID'"/>
                                        <xsl:attribute name="Value" namespace="" select="fn:string(@ItemValue)"/>
                                    </ItemData>
                                </xsl:for-each>
                                <xsl:for-each select="$var8_resultof_filter[fn:starts-with(fn:string(@ItemOID), 'IT.dm_birthyr')][fn:exists(@ItemValue)]">
                                    <ItemData>
                                        <xsl:attribute name="ItemOID" namespace="" select="'IT.DM.BRTHDTC'"/>
                                        <xsl:attribute name="Value" namespace="" select="fn:string(@ItemValue)"/>
                                    </ItemData>
                                </xsl:for-each>
                                <xsl:for-each select="$var8_resultof_filter[fn:starts-with(fn:string(@ItemOID), 'IT.dm_sex')][fn:exists(@ItemValue)]">
                                    <ItemData>
                                        <xsl:attribute name="ItemOID" namespace="" select="'IT.DM.SEX'"/>
                                        <xsl:attribute name="Value" namespace="" select="fn:string(@ItemValue)"/>
                                    </ItemData>
                                </xsl:for-each>
                                <xsl:if test="(fn:not($var4_resultof_equal) or fn:exists($var6_resultof_filter[fn:exists(@ItemValue)]))">
                                    <ItemData>
                                        <xsl:attribute name="ItemOID" namespace="" select="'IT.DM.RACE'"/>
                                        <xsl:attribute name="Value" namespace="">
                                            <xsl:choose>
                                                <xsl:when test="$var4_resultof_equal">
                                                    <xsl:variable name="var2_resultof_map" as="xs:string*">
                                                        <xsl:for-each select="$var5_resultof_filter">
                                                            <xsl:sequence select="fn:string(@ItemValue)"/>
                                                        </xsl:for-each>
                                                    </xsl:variable>
                                                    <xsl:sequence select="xs:string(fn:string-join(for $x in $var2_resultof_map return xs:string($x), ' '))"/>
                                                </xsl:when>
                                                <xsl:otherwise>
                                                    <xsl:sequence select="'MULTIPLE'"/>
                                                </xsl:otherwise>
                                            </xsl:choose>
                                        </xsl:attribute>
                                    </ItemData>
                                </xsl:if>
                                <xsl:for-each select="$var8_resultof_filter[fn:starts-with(fn:string(@ItemOID), 'IT.dm_ethnic')][fn:exists(@ItemValue)]">
                                    <ItemData>
                                        <xsl:attribute name="ItemOID" namespace="" select="'IT.DM.ETHNIC'"/>
                                        <xsl:attribute name="Value" namespace="" select="fn:string(@ItemValue)"/>
                                    </ItemData>
                                </xsl:for-each>
                                <ItemData>
                                    <xsl:if test="fn:exists($var7_resultof_vmf__inputtoresult)">
                                        <xsl:attribute name="Value" namespace="" select="$var7_resultof_vmf__inputtoresult"/>
                                    </xsl:if>
                                </ItemData>
                            </ItemGroupData>
                        </xsl:for-each>
                    </ClinicalData>
                </xsl:for-each>
            </xsl:for-each>
        </ODM>
    </xsl:template>
   </xsl:stylesheet>

and the Java code:

        Processor processor = new Processor(true);
    processor.registerExtensionFunction(new GenerateAutoNumberExtDefinition());
    processor.registerExtensionFunction(new ResetAutoNumberExtDefinition());

    XdmNode input = processor.newDocumentBuilder().build(inputXML);
    Xslt30Transformer transformer = processor.newXsltCompiler().compile(xsltSource).load30();
    StringWriter outputStream = new StringWriter();
    transformer.applyTemplates(input, processor.newSerializer(outputStream));

Where the GenerateAutoNumberExtDefinition implement increment of variable. I even try to debug this and I am sure that it's called only once.

And the result XML is :

    <?xml version="1.0" encoding="UTF-8"?>
<ODM xmlns="http://www.cdisc.org/ns/odm/v1.3"
     xmlns:data="http://www.cdisc.org/ns/Dataset-XML/v1.0"
     FileType="Snapshot"
     ODMVersion="1.3.2"
     data:DatasetXMLVersion="1.0.0"
     FileOID="c293a323-31a0-4df3-94b4-2876f62b8193"
     CreationDateTime="2015-10-01T15:41:57.216-04:00">
   <ClinicalData StudyOID="Some OID"
                 MetaDataVersionOID="2015-06-30T09:45:09.000-04:00">
      <ItemGroupData ItemGroupOID="IG.DM" data:ItemGroupDataSeq="1">
         <ItemData ItemOID="IT.STUDYID" Value="Some OID"/>
         <ItemData ItemOID="IT.DM.DOMAIN" Value="DM"/>
         <ItemData ItemOID="IT.USUBJID" Value="11"/>
         <ItemData ItemOID="IT.DM.SUBJID" Value="11"/>
         <ItemData ItemOID="IT.DM.SEX" Value="F"/>
         <ItemData ItemOID="IT.DM.RACE" Value="ASIAN"/>
         <ItemData ItemOID="IT.DM.ETHNIC" Value="HISPANIC_OR_LATINO"/>
         <ItemData/>
      </ItemGroupData>
      <ItemGroupData ItemGroupOID="IG.DM" data:ItemGroupDataSeq="1">
         <ItemData ItemOID="IT.STUDYID" Value="Some OID"/>
         <ItemData ItemOID="IT.DM.DOMAIN" Value="DM"/>
         <ItemData ItemOID="IT.USUBJID" Value="12"/>
         <ItemData ItemOID="IT.DM.SUBJID" Value="12"/>
         <ItemData ItemOID="IT.DM.SEX" Value="M"/>
         <ItemData ItemOID="IT.DM.RACE" Value="MULTIPLE"/>
         <ItemData ItemOID="IT.DM.ETHNIC" Value="HISPANIC_OR_LATINO"/>
         <ItemData/>
      </ItemGroupData>
      <ItemGroupData ItemGroupOID="IG.DM" data:ItemGroupDataSeq="1">
         <ItemData ItemOID="IT.STUDYID" Value="Some OID"/>
         <ItemData ItemOID="IT.DM.DOMAIN" Value="DM"/>
         <ItemData ItemOID="IT.USUBJID" Value="14"/>
         <ItemData ItemOID="IT.DM.SUBJID" Value="14"/>
         <ItemData ItemOID="IT.DM.SEX" Value="M"/>
         <ItemData ItemOID="IT.DM.RACE" Value="NATIVE_HAWAIIAN_OR_OTHER_PACIFIC_ISLANDER"/>
         <ItemData ItemOID="IT.DM.ETHNIC" Value="NOT_HISPANIC_OR_LATINO"/>
         <ItemData/>
      </ItemGroupData>
      <ItemGroupData ItemGroupOID="IG.DM" data:ItemGroupDataSeq="1">
         <ItemData ItemOID="IT.STUDYID" Value="Some OID"/>
         <ItemData ItemOID="IT.DM.DOMAIN" Value="DM"/>
         <ItemData ItemOID="IT.USUBJID" Value="12344"/>
         <ItemData ItemOID="IT.DM.SUBJID" Value="12344"/>
         <ItemData ItemOID="IT.DM.SEX" Value="UNDIFFERENTIATED"/>
         <ItemData ItemOID="IT.DM.RACE" Value="MULTIPLE"/>
         <ItemData ItemOID="IT.DM.ETHNIC" Value="UNKNOWN"/>
         <ItemData/>
      </ItemGroupData>
      <ItemGroupData ItemGroupOID="IG.DM" data:ItemGroupDataSeq="1">
         <ItemData ItemOID="IT.STUDYID" Value="Some OID"/>
         <ItemData ItemOID="IT.DM.DOMAIN" Value="DM"/>
         <ItemData ItemOID="IT.USUBJID" Value="22333"/>
         <ItemData ItemOID="IT.DM.SUBJID" Value="22333"/>
         <ItemData ItemOID="IT.DM.RACE" Value="MULTIPLE"/>
         <ItemData/>
      </ItemGroupData>
      <ItemGroupData ItemGroupOID="IG.DM" data:ItemGroupDataSeq="1">
         <ItemData ItemOID="IT.STUDYID" Value="Some OID"/>
         <ItemData ItemOID="IT.DM.DOMAIN" Value="DM"/>
         <ItemData ItemOID="IT.USUBJID" Value="22334"/>
         <ItemData ItemOID="IT.DM.SUBJID" Value="22334"/>
         <ItemData ItemOID="IT.DM.RACE" Value="MULTIPLE"/>
         <ItemData/>
      </ItemGroupData>
      <ItemGroupData ItemGroupOID="IG.DM" data:ItemGroupDataSeq="1">
         <ItemData ItemOID="IT.STUDYID" Value="Some OID"/>
         <ItemData ItemOID="IT.DM.DOMAIN" Value="DM"/>
         <ItemData ItemOID="IT.USUBJID" Value="22335"/>
         <ItemData ItemOID="IT.DM.SUBJID" Value="22335"/>
         <ItemData ItemOID="IT.DM.RACE" Value="MULTIPLE"/>
         <ItemData/>
      </ItemGroupData>
      <ItemGroupData ItemGroupOID="IG.DM" data:ItemGroupDataSeq="1">
         <ItemData ItemOID="IT.STUDYID" Value="Some OID"/>
         <ItemData ItemOID="IT.DM.DOMAIN" Value="DM"/>
         <ItemData ItemOID="IT.USUBJID" Value="22336"/>
         <ItemData ItemOID="IT.DM.SUBJID" Value="22336"/>
         <ItemData ItemOID="IT.DM.SEX" Value="F"/>
         <ItemData ItemOID="IT.DM.RACE" Value="MULTIPLE"/>
         <ItemData ItemOID="IT.DM.ETHNIC" Value="NOT_REPORTED"/>
         <ItemData/>
      </ItemGroupData>
   </ClinicalData>
</ODM>

as you can see in each data:ItemGroupDataSeq the value is "1" but it's should increment.

2 Answers 2

0

Can't you solve that simply with pure XSLT? <xsl:attribute name="data:ItemGroupDataSeq"><xsl:number/></xsl:attribute> or even <xsl:attribute name="data:ItemGroupDataSeq" select="position()"/> inside the for-each over Patient elements should do.

If you need help with the extension functions then we need to see their implementation.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for help. Actually your way is worked. But not for my specific case, when i need some times reset counter and start count again (what function <xsl:sequence select="ns0:reset-auto-number('mapforce_autonumber_153336056')"/> is doing).
0

Actually way described above is worked. But not for my specific case, when i need some times reset counter and start count again (what function is doing).

But it's problem I can solve by overriding function dependsOnFocus in ExtensionFunctionDefinition class.

@Override
public boolean dependsOnFocus() {
    return true;
}

If the value is false, it's looks like a cache. If parameters not changes, that the function called only once. Returning true by dependsOnFocus method allow us depend on function position in xslt not on parameters.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.