code-gijoe
code-gijoe

Reputation: 7234

how to merge nodes (withe same name) to single node output using xslt?

I would like to merge nodes such as:

<sourcePatientInfo>PID-3|1428eab4645a4ce^^^&amp;1.3.6.1.4.1.21367.2008.2.1&amp;ISO</sourcePatientInfo>
<sourcePatientInfo>PID-5|WILKINS^CHARLES^^^</sourcePatientInfo>
<sourcePatientInfo>PID-8|M</sourcePatientInfo>

To a single node like this (don't worry about the node value, I have it handled):

   <sourcePatientInfo>
      <patientIdentifier>
      </patientIdentifier>
      <patientName>
      </patientName>
      <patientSex></patientSex>
   </sourcePatientInfo>

If found a few posts: post 1 Post 2

But they are merging nodes with different names in the source xml. For now I have this:

<xsl:template match="sourcePatientInfo">
    <sourcePatientInfo>
        <xsl:choose>
            <xsl:when test="matches(., 'PID-3')">
            <patientIdentifier />
            </xsl:when>
            <xsl:when test="matches(., 'PID-5')">
            <patientName />
            </xsl:when>
            <xsl:when test="matches(., 'PID-8')">
            <patientSex />
            </xsl:when>                 
        </xsl:choose>
    </sourcePatientInfo>
</xsl:template>

I excluded some details to avoid to much code. What I get with it is 3 separate sourcePatientInfo which is no good.

Any help? Thank you!!!!

Upvotes: 2

Views: 556

Answers (1)

user357812
user357812

Reputation:

This stylesheet:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:l="http://localhost"
 exclude-result-prefixes="l">
    <l:n id="PID-3">patientIdentifier</l:n>
    <l:n id="PID-5">patientName</l:n>
    <l:n id="PID-8">patientSex</l:n>
    <xsl:variable name="vNames" select="document('')/*/l:n"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="sourcePatientInfo"/>
    <xsl:template match="sourcePatientInfo[1]">
        <xsl:copy>
            <xsl:apply-templates
             select=".|following-sibling::sourcePatientInfo"
             mode="merge"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="sourcePatientInfo" mode="merge">
        <xsl:apply-templates 
             select="$vNames[@id=substring-before(current(),'|')]">
            <xsl:with-param name="pCurrent" select="."/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="l:n">
        <xsl:param name="pCurrent" select="/.."/>
        <xsl:element name="{.}">
            <xsl:value-of select="substring-after($pCurrent,'|')"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

With this input:

<item>
    <sourcePatientInfo>PID-3|1428eab4645a4ce^^^&amp;1.3.6.1.4.1.21367.2008.2.1&amp;ISO</sourcePatientInfo>
    <sourcePatientInfo>PID-5|WILKINS^CHARLES^^^</sourcePatientInfo>
    <sourcePatientInfo>PID-8|M</sourcePatientInfo>
</item>

Output:

<item>
    <sourcePatientInfo>
        <patientIdentifier>1428eab4645a4ce^^^&amp;1.3.6.1.4.1.21367.2008.2.1&amp;ISO</patientIdentifier>
        <patientName>WILKINS^CHARLES^^^</patientName>
        <patientSex>M</patientSex>
    </sourcePatientInfo>
</item>

EDIT: Applying templates to inline map's nodes for "complex" further processing.

Upvotes: 6

Related Questions