user481779
user481779

Reputation: 1081

Named template with mode not outputting expected node data

I have the following Input, Transform and Output XML. The Output XML is not what I am expecting. I am attempting to use the mode attribute in my templates to separate my processing into two steps. Step1 filters the Input XML and Step2 processes specific nodes in what I am hoping is the filtered Input XML. My Step2 templates simply output what they receive so I am expecting to see the full description of the nodes selected for each template. The Output XML contains only the top-level node labels (Patient,Encounters,Diagnoses) and only the text of the node itself.

I have the following XSLT fiddle at My XSLT fiddle that shows my issue, I hope clearly.

Input XML

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <Container>
    <Patient>
      <BirthTime>2001-01-01T00:00:00Z</BirthTime>
    </Patient>
    <Encounters>
      <Encounter>
        <EncounterNumber>1</EncounterNumber>
        <FromTime>2021-04-01T00:00:00Z</FromTime>
      </Encounter>
      <Encounter>
        <EncounterNumber>2</EncounterNumber>
        <FromTime>2021-03-01T00:00:00Z</FromTime>
      </Encounter>
    </Encounters>
    <Diagnoses>
      <Diagnosis>
        <EncounterNumber>1</EncounterNumber>
      </Diagnosis>
      <Diagnosis>
        <EncounterNumber>2</EncounterNumber>
      </Diagnosis>
    </Diagnoses>
  </Container>
</root>

Transform XML

<?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:math="http://www.w3.org/2005/xpath-functions/math"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns:array="http://www.w3.org/2005/xpath-functions/array"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:variable name="encounterNumbers">
    <EncounterNumber>2</EncounterNumber>
  </xsl:variable>

  <!-- START PROCESSING -->
  <xsl:template match="node()|@*">
    <xsl:apply-templates select="." mode="step1"/>
  </xsl:template>

  <!-- STEP1 TEMPLATES -->
  <xsl:template name="filterSDA" mode="step1" match="node()|@*">
    <xsl:variable name="filteredSDA">
      <xsl:copy>
        <xsl:apply-templates select="node()|@*" />
      </xsl:copy>
    </xsl:variable>

    <xsl:apply-templates select="$filteredSDA" mode="step2"/>

  </xsl:template>
  
  <xsl:template match="//Encounters/Encounter[not(EncounterNumber = $encounterNumbers/EncounterNumber)]" mode="step1"/>
  <xsl:template match="//Diagnoses/Diagnosis[not(EncounterNumber = $encounterNumbers/EncounterNumber)]"  mode="step1"/>

  <!-- STEP2 TEMPLATES -->
  <xsl:template name="demographics" mode="step2" match="Patient">

    <xsl:copy-of select="." />
  </xsl:template>

  <xsl:template name="clinical" mode="step2" match="Encounters|Diagnoses">

    <xsl:copy-of select="." />
  </xsl:template>

</xsl:stylesheet>

Output XML

<?xml version="1.0" encoding="UTF-8"?>
<Patient>
      2001-01-01T00:00:00Z
    </Patient>
<Encounters>
      
      
        2
        2021-03-01T00:00:00Z
      
      
    </Encounters>
<Diagnoses>
      
      
        2
      
    </Diagnoses>

Upvotes: 0

Views: 45

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167696

I think you are overcomplicating things by mixing named templates (which you seem to call nowhere) with matching templates.

Furthermore, if you want a two phase processing with two different modes, I would do that at the top level, pushing the result of processing the whole input through the first mode into a variable and then applying the second mode on that variable:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:variable name="encounterNumbers">
    <EncounterNumber>2</EncounterNumber>
    <EncounterNumber>3</EncounterNumber>
    <EncounterNumber>4</EncounterNumber>
  </xsl:variable>
  
  <xsl:mode name="step1" on-no-match="shallow-copy"/>
  
  <xsl:mode name="step2" on-no-match="shallow-copy"/>

  <!-- START PROCESSING -->
  <xsl:template match="/">
    <xsl:variable name="step-1-result">
      <xsl:apply-templates mode="step1"/>
    </xsl:variable>
    <xsl:apply-templates select="$step-1-result/node()" mode="step2"/>
  </xsl:template>
  
  <!-- mode step1 templates -->
  <xsl:template match="//Encounters/Encounter[not(EncounterNumber = $encounterNumbers/EncounterNumber)]" mode="step1"/>
  <xsl:template match="//Diagnoses/Diagnosis[not(EncounterNumber = $encounterNumbers/EncounterNumber)]"  mode="step1"/>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/asoTKZ/20

Upvotes: 1

Related Questions