使用唯一(主键)字段对XML数据进行分组

使用唯一(主键)字段对XML数据进行分组,xml,ms-access,xslt,grouping,Xml,Ms Access,Xslt,Grouping,我是个新手,对XML数据进行分组时遇到问题。我的数据如下(文件的第一部分是500例的病例(患者)数据,文件的最后部分是这些病例的诊断和手术数据): 2736 2736 15569 854471.2 腓骨骨折,左骨干 假的 2736 15570 854251.2 左侧胫骨干骨折 假的 262 2012-03-13 假的 2736 15570 854251.2 左侧胫骨干骨折 假的 261 2012-03-13 真的 还原和层粘连治疗还原和层粘连治疗 因此,一个病例可以有0…n诊断,一个诊断可以

我是个新手,对XML数据进行分组时遇到问题。我的数据如下(文件的第一部分是500例的病例(患者)数据,文件的最后部分是这些病例的诊断和手术数据):


2736
2736
15569
854471.2
腓骨骨折,左骨干
假的
2736
15570
854251.2
左侧胫骨干骨折
假的
262
2012-03-13
假的
2736
15570
854251.2
左侧胫骨干骨折
假的
261
2012-03-13
真的
还原和层粘连治疗还原和层粘连治疗
因此,一个病例可以有0…n诊断,一个诊断可以有0…n手术(=手术)。其中一项操作应勾选为主要操作

我的代码如下:

<!--   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>

我希望得到的结果是所有诊断的列表(每个唯一的诊断只列出一次):


854471.2
腓骨骨折,左骨干
854251.2
左侧胫骨干骨折
2012-03-13
还原和层粘连治疗还原和层粘连治疗
Diagnostic ID是原始数据库中的主键字段,可用于对诊断进行分组。但我不知道该怎么做。我需要的是所有诊断(用所谓的AIS代码编码),如果有手术(=手术)或与诊断相关的手术,我需要主要的手术信息(不显示次要的、不太重要的手术)。目前的情况是,如果有多个操作与一个诊断相关,我会多次得到相同的诊断


我研究了慕尼黑分类法,但我不认为这在这里是必要的,因为我有一个唯一的关键字段,可以识别每个诊断。还是这样?我很抱歉问了这么长(模糊?)的问题,但我对这个问题很陌生,不知道如何继续。感谢您的帮助

以下样式表:

<?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>

当应用于上述输入XML时,结果为:

<?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>

854471.2
腓骨骨折,左骨干
854251.2
左侧胫骨干骨折
2012-03-13
还原和层粘连治疗还原和层粘连治疗
我研究了明钦族的分类,但我认为这没有必要 这里

好吧,你确实需要一些东西来得到明确的诊断——要么是门钦族的分类,要么是主题上的一些变异。下面是它如何工作的快速演示:

<?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>

应用于您的输入,将获得以下结果:

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

或者,如果处理器支持EXSLT distinct()函数,也可以使用它


编辑: 下面是一个更接近预期结果的扩展版本:

<?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>

结果

<?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>

854471.2
腓骨骨折,左骨干
854251.2
左侧胫骨干骨折
2012-03-13
还原和层粘连治疗还原和层粘连治疗

感谢您的输入!然而,这里仍然存在原始问题,即每个唯一的诊断应该只在结果中出现一次。此处左侧的854251.2胫骨骨折轴(原始诊断ID=15570)打印了两次,应该只显示一次(然后是手术等细节)。@Garcanrya我编辑了我的答案。请检查这是否解决了您的问题。不幸的是,我无法使这项工作(至少还没有)。结果是,所有诊断都像以前一样打印出来,而且每个患者病例都有所有其他患者的所有诊断。不确定问题是我的实现还是这里提供的代码。好吧,我想你必须在这个问题中更多地定义你的输入XML,这样解决方案才能更接近你真正的问题。谢谢,这确实选择了每一个诊断
<?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>
<?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>