Domanda

I'm a newbie and have problems with grouping XML data. My data is like this (first part of the file is case (patient) data of 500 cases and the end part of the file diagnose and surgery data of those cases):

<?xml version="1.0" encoding="UTF-8"?>
    <rootCases>
    <caselist>
        <row>
             <CaseID>2736</CaseID>
             <!-- 500 cases and their information -->
        </row>
    </caselist>

    <!-- Diagnoses and operations start here -->

    <rootDiagnoses>
        <row>
            <CaseID>2736</CaseID>
            <DiagnoseID>15569</DiagnoseID>
            <AIS>854471.2</AIS>
            <Description>Fibula fracture, shaft on left</Description>
            <Main_Diagnose>false</Main_Diagnose>
            <OperationsID/>
            <SurgeryDate/>
            <Main_surgery/>
            <Operation_text/>
        </row>

        <row>
            <CaseID>2736</CaseID>
            <DiagnoseID>15570</DiagnoseID>
            <AIS>854251.2</AIS>
            <Description>Tibia fracture shaft on left</Description>
            <Main_Diagnose>false</Main_Diagnose>
            <OperationsID>262</OperationsID>
            <SurgeryDate>2012-03-13</SurgeryDate>
            <Main_surgery>false</Main_surgery>
            <Operation_text/>
        </row>
        <row>
            <CaseID>2736</CaseID>
            <DiagnoseID>15570</DiagnoseID>
            <AIS>854251.2</AIS>
            <Description>Tibia fracture shaft on left</Description>
            <Main_Diagnose>false</Main_Diagnose>
            <OperationsID>261</OperationsID>
            <SurgeryDate>2012-03-13</SurgeryDate>
            <Main_surgery>true</Main_surgery>
            <Operation_text>Reductio et laminofixatio Reductio et laminofixatio</Operation_text>
        </row>
    </rootDiagnoses>
</rootCases>

So a case can have 0...n diagnosis and a diagnose can have 0...n operations (=surgeries). One of those operations should be ticked as a main operation.

My code is as follows:

<!--   Begin diagnoses list Element   -->
<xsl:variable name="caseident" select="CaseID" />
  <xsl:choose>
    <xsl:when test="/rootCases/rootDiagnoses/row/CaseID[text()=$caseident]/../AIS !=''">
      <diagnosisList>
        <xsl:for-each select="/rootCases/rootDiagnoses/row[CaseID=$caseident]">
        <!-- ERROR: Multiple diagnoses inserted when patient has 
             multiple operations per diagnose -->
           <xsl:if test="AIS !=''"><diagnosis>
              <ais2005Code><xsl:value-of select="AIS"/></ais2005Code>
              <descriptionDiagnosis><xsl:value-of select="Description"/></descriptionDiagnosis>
              <xsl:if test="SurgeryDate !='' and Main_surgery ='true'"><surgery1>
                  <date><xsl:value-of select="SurgeryDate"/></date>
                  <description><xsl:value-of select="Operation_text"/></description>
               </surgery1></xsl:if>
            </diagnosis></xsl:if>
         </xsl:for-each>
       </diagnosisList>
   </xsl:when>
  <xsl:otherwise><noDiagnosisList/></xsl:otherwise>
  </xsl:choose>

What I would like to have as a result would be a list of all diagnoses (each unique diagnose listed only once):

<!--     Diagnoses List Element of patient 2736-->
<diagnosisList>
        <diagnosis>
           <ais2005Code>854471.2</ais2005Code>
           <descriptionDiagnosis>Fibula fracture, shaft on left</descriptionDiagnosis>
        </diagnosis>
        <diagnosis>
           <ais2005Code>854251.2</ais2005Code>
           <descriptionDiagnosis>Tibia fracture shaft on left</descriptionDiagnosis>
           <surgery1>
              <date>2012-03-13</date>
              <description>Reductio et laminofixatio Reductio et laminofixatio</description>
           </surgery1>
         </diagnosis>
</diagnosisList>

DiagnoseID is a primary key field in my original database and could be used for grouping the diagnose. But I'm not sure how to do this. What I need is all diagnoses (coded with so called AIS-codes) and if there's an operation (=surgery) or operations related to a diagnose, I need the main surgery information (the secondary, not so important surgeries are not shown). At the moment what happens is, that if there are multiple operations related to a diagnose, I get multiple times the same diagnose.

I looked into Muenchian grouping, but I don't think that is necessary here, since I have a unique key field that identifies each diagnosis already. Or is this so? I'm sorry for the long (vague?) question, but I'm really new with this and don't know how to proceed. All help is appreciated!

È stato utile?

Soluzione

I looked into Muenchian grouping, but I don't think that is necessary here

Well, you do need something to get only distinct diagnoses - either Muenchian grouping or some variation on the theme. Here's a quick demo of how it could work:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="diag-by-case" match="rootDiagnoses/row" use="CaseID" />
<xsl:key name="diag-by-diag" match="rootDiagnoses/row" use="DiagnoseID" />

<xsl:template match="/">
    <output>
        <xsl:for-each select="rootCases/caselist/row">
        <case id="{CaseID}">
            <!-- for each unique diagnosis -->
            <xsl:for-each select="key('diag-by-case', CaseID)[count(. | key('diag-by-diag', DiagnoseID)[1]) = 1]">
                <diagnosis id="{DiagnoseID}">
                </diagnosis>
            </xsl:for-each>
        </case> 
        </xsl:for-each>
    </output>
</xsl:template>

</xsl:stylesheet>

Applied to your input, the following result is obtained:

<?xml version="1.0" encoding="UTF-8"?>
<output>
  <case id="2736">
    <diagnosis id="15569"/>
    <diagnosis id="15570"/>
  </case>
</output>

Alternatively, you could use the EXSLT distinct() function, if your processor supports it.


Edit:

Here's an expanded version that gets closer to your intended result:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="diag-by-case" match="rootDiagnoses/row" use="CaseID" />
<xsl:key name="diag-by-diag" match="rootDiagnoses/row" use="DiagnoseID" />

<xsl:template match="/">
    <output>
        <xsl:for-each select="rootCases/caselist/row">
        <case id="{CaseID}">
            <!-- for each unique diagnosis -->
            <xsl:for-each select="key('diag-by-case', CaseID)[count(. | key('diag-by-diag', DiagnoseID)[1]) = 1]">
                <diagnosis id="{DiagnoseID}">
                    <ais2005Code><xsl:value-of select="AIS"/></ais2005Code>
                    <descriptionDiagnosis><xsl:value-of select="Description"/></descriptionDiagnosis>
                    <!-- get surgery -->
                    <xsl:for-each select="key('diag-by-diag', DiagnoseID)[Main_surgery='true']">
                        <surgery1>
                            <date><xsl:value-of select="SurgeryDate"/></date>
                            <description><xsl:value-of select="Operation_text"/></description>
                        </surgery1>
                    </xsl:for-each>
                </diagnosis>
            </xsl:for-each>
        </case> 
        </xsl:for-each>
    </output>
</xsl:template>

Result:

<?xml version="1.0" encoding="UTF-8"?>
<output>
   <case id="2736">
      <diagnosis id="15569">
         <ais2005Code>854471.2</ais2005Code>
         <descriptionDiagnosis>Fibula fracture, shaft on left</descriptionDiagnosis>
      </diagnosis>
      <diagnosis id="15570">
         <ais2005Code>854251.2</ais2005Code>
         <descriptionDiagnosis>Tibia fracture shaft on left</descriptionDiagnosis>
         <surgery1>
            <date>2012-03-13</date>
            <description>Reductio et laminofixatio Reductio et laminofixatio</description>
         </surgery1>
      </diagnosis>
   </case>
</output>

Altri suggerimenti

the following stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <xsl:variable name="diagnoses" select="rootCases/rootDiagnoses"/>
        <xsl:for-each select="rootCases/caselist/row/CaseID">
            <xsl:variable name="curr_ID" select="."/>
            <diagnosisList id="{$curr_ID}">
            <xsl:for-each select="$diagnoses/row[CaseID = $curr_ID]">
                <xsl:variable name="curr_DiagnoseID" select="DiagnoseID"/>
                <xsl:choose>
                    <!-- checks following rows and preceding rows 
                        of the current row if it has duplicate DiagnoseID.
                        If found, checks whether if the current row has 
                        a child Main_surgery = true. If none found, 
                        the current node outputs nothing.
                    -->
                    <xsl:when test="$curr_DiagnoseID = following-sibling::row/DiagnoseID or $curr_DiagnoseID = preceding-sibling::row/DiagnoseID">
                        <xsl:if test="current()/Main_surgery = 'true'">
                            <diagnosis>
                                <ais2005Code><xsl:value-of select="descendant::AIS"/></ais2005Code>
                                <description><xsl:value-of select="descendant::Description"/></description>
                                <surgery1>
                                    <date><xsl:value-of select="descendant::SurgeryDate"/></date>
                                    <description><xsl:value-of select="descendant::Operation_text"/></description>
                                </surgery1>
                            </diagnosis>
                        </xsl:if>
                    </xsl:when>
                    <xsl:otherwise>
                        <diagnosis>
                            <ais2005Code><xsl:value-of select="descendant::AIS"/></ais2005Code>
                            <description><xsl:value-of select="descendant::Description"/></description>
                            <xsl:if test="descendant::Main_surgery = 'true'">
                                <surgery1>
                                    <date><xsl:value-of select="descendant::SurgeryDate"/></date>
                                    <description><xsl:value-of select="descendant::Operation_text"/></description>
                                </surgery1>
                            </xsl:if>
                        </diagnosis>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
            </diagnosisList>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

when applied to the input XML above, results in:

<?xml version="1.0" encoding="utf-8"?>
<diagnosisList id="2736">
   <diagnosis>
      <ais2005Code>854471.2</ais2005Code>
      <description>Fibula fracture, shaft on left</description>
   </diagnosis>
   <diagnosis>
      <ais2005Code>854251.2</ais2005Code>
      <description>Tibia fracture shaft on left</description>
      <surgery1>
         <date>2012-03-13</date>
         <description>Reductio et laminofixatio Reductio et laminofixatio</description>
      </surgery1>
   </diagnosis>
</diagnosisList>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top