XSLT1如何可靠地从具有可变数量子节点的父节点获取数据

问题描述 投票:0回答:3

我有这个非常大的XML文件包含真正的老动物测试数据,每行包含一组字段,但每个字段也会再次填充多个字段。该文件使用子序列来确定实际数据之间的关系。

我需要按照“第一个所有第一个数据字段”的顺序提取这些字段,然后是所有第二个数据字段,然后是第三个......等等。但是数据字段的数量并不是针对不同的行设置的,只是在同一行中它似乎是一致的。

很难解释,但我添加了一个示例文档,第一个表是源,第二个表是我想要的地方。

我尝试了类似下面的东西来保存节点关系,但我无法让它工作。我说我只是刚刚超过xslt的初学者级别,但是由于当前的基础设施要求,我需要在XSLT1中使用它;

<xsl:template match="ROW">
    <xsl:for-each select="./anamnese/DATA">
        <xsl:variable name="depth">
            <xsl:number/>
        </xsl:variable>
        <xsl:value-of select=".//anamnese/DATA[$depth]"/>
        <xsl:value-of select=".//diagnose/DATA[$depth]"/>
        <xsl:value-of select=".//fichenr./DATA[$depth]"/>
        <xsl:value-of select=".//vis/DATA[$depth]"/>
        <xsl:value-of select=".//dr._A/DATA[$depth]"/>
    </xsl:for-each>
</xsl:template>

具有伪造数据的起始表的示例。注意DATA字段在当前数量中是如何不可靠的。

<TABLE>
    <ROW MODID="4" RECORDID="1801">
        <anamnese>
            <DATA>Gevonden in lat decubitus. Dag van huis weggeweest. Vanmorgen nog goed gegeten.</DATA>
        </anamnese>
        <diagnose>
            <DATA/>
        </diagnose>
        <fichenr.>
            <DATA>3607</DATA>
        </fichenr.>
        <vis>
            <DATA>25/08/2017</DATA>
        </vis>
        <dr._A>
            <DATA>EL</DATA>
        </dr._A>
    </ROW>
    <ROW MODID="6" RECORDID="1802">
        <anamnese>
            <DATA>zeer agressief geworden op korte tijd</DATA>
            <DATA/>
            <DATA>detartratie nodig. Eerst cardiologisch onderzoek gehad bij Valerie Bavegems. Verslag volgt nog. Drinkt redelijk veel, 500 g afgevallen</DATA>
        </anamnese>
        <diagnose>
            <DATA> euthanasie</DATA>
            <DATA/>
            <DATA/>
        </diagnose>
        <fichenr.>
            <DATA>3989</DATA>
            <DATA>3688</DATA>
            <DATA>3608</DATA>
        </fichenr.>
        <vis>
            <DATA>2/11/2017</DATA>
            <DATA>6/09/2017</DATA>
            <DATA>26/08/2017</DATA>
        </vis>
        <dr._A>
            <DATA>EL</DATA>
            <DATA>EL</DATA>
            <DATA>MA</DATA>
        </dr._A>
    </ROW>
    <ROW MODID="4" RECORDID="1803">
        <anamnese/>
        <diagnose/>
        <fichenr./>
        <vis/>
        <dr._A/>
    </ROW>
</TABLE>

期望的最终产品;

<TABLE_B>
    <ROW>
        <recordId>1801</recordId>
        <anamnese>Gevonden in lat decubitus. Vanmorgen nog goed gegeten.</anamnese>
        <diagnose></diagnose>
        <fichenr.>3607</fichenr.>
        <vis>25/08/2017</vis>
        <dr._A>EL</dr._A>
    </ROW>
    <ROW>
        <recordId>1802</recordId>
        <anamnese>zeer agressief geworden op korte tijd</anamnese>
        <diagnose> euthanasie</diagnose>
        <fichenr.>3989</fichenr.>
        <vis>2/11/2017</vis>
        <dr._A></dr._A>
    </ROW>
    <ROW>
        <recordId>1802</recordId>
        <anamnese/>
        <diagnose></diagnose>
        <fichenr.>3688</fichenr.>
        <vis>6/09/2017</vis>
        <dr._A>EL</dr._A>
    </ROW>
    <ROW>
        <recordId>1802</recordId>
        <anamnese>detartratie nodig. Eerst cardiologisch onderzoek gehad bij Valerie Bavegems. Verslag volgt nog. Drinkt redelijk veel, 500 g afgevallen</anamnese>
        <diagnose/>
        <fichenr.>3608</fichenr.>
        <vis>26/08/2017</vis>
        <dr._A>MA</dr._A>
    </ROW>
    <ROW>
        <recordId>1803</recordId>
        <anamnese/>
        <diagnose/>
        <fichenr./>
        <vis/>
        <dr._A/>
    </ROW>
</TABLE_B>

即使我无法预测连续可能的MAX字段数量,如何可靠地提取所有正确关系的DATA字段? (我在视觉上看到了一行有266:p)

java xslt-1.0
3个回答
0
投票

我假设节点anamnese指示要生成的行数。如果它有3个孩子,它将产生3行。如果它是空的,则不应该跟随信息。我只是复制了节点。

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

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

    <xsl:template match="TABLE">
        <TABLE_B>
            <xsl:apply-templates/>
        </TABLE_B>
    </xsl:template>

    <xsl:template match="ROW">
        <xsl:variable name="ID" select="@RECORDID"/>
            <xsl:choose>
                <!-- Test for anamnese children.
                     If there is no child element,
                     copy the ROW child elements
                -->
                <xsl:when test="not(anamnese/*)">
                    <ROW>
                        <recordId>
                            <xsl:value-of select="$ID"/>
                        </recordId>
                        <xsl:copy-of select="*"/>
                    </ROW>
                </xsl:when>
                <xsl:otherwise>
                    <!-- if there exists anamnese children,
                         loop through these.-->
                    <xsl:for-each select="anamnese/*">
                        <xsl:variable name="pos" select="position()"/>
                        <ROW>
                            <recordId>
                                <xsl:value-of select="$ID"/>
                            </recordId>
                            <anamnese>
                                <xsl:value-of select="."/>
                            </anamnese>
                            <!-- loop through the following siblings of anamnese -->
                            <xsl:for-each select="../following-sibling::*">
                                <xsl:element name="{local-name()}">
                                    <!-- select nodes with the same position -->
                                    <xsl:value-of select="*[position()=$pos]"/>
                                </xsl:element>
                            </xsl:for-each>
                        </ROW>
                    </xsl:for-each>
                </xsl:otherwise>
            </xsl:choose>
    </xsl:template>


</xsl:stylesheet>

0
投票

如果ROW块结构是静态的,你可以先用参数在单独的模板中定义ROW块结构,然后在必需的循环中传递它的参数,见下面的XSL:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">       
    <!--prepare template for ROW block structure-->
    <xsl:template name="row">
        <!--pass recordId value-->
        <xsl:param name="rec.id"/>
        <!--pass ROW position number value-->
        <xsl:param name="row.id"/>
        <!--pass DATA position number value-->
        <xsl:param name="data.id"/>
        <!--creating ROW structure-->
        <ROW>
            <recordId>
                <xsl:value-of select="$rec.id"/>
            </recordId>
            <anamnese>
                <xsl:value-of select="//ROW[$row.id]/anamnese/DATA[$data.id]"/>
            </anamnese>
            <diagnose>
                <xsl:value-of select="//ROW[$row.id]/diagnose/DATA[$data.id]"/>
            </diagnose>
            <fichenr.>
                <xsl:value-of select="//ROW[$row.id]/fichenr./DATA[$data.id]"/>
            </fichenr.>
            <vis>
                <xsl:value-of select="//ROW[$row.id]/vis/DATA[$data.id]"/>
            </vis>
            <dr._A>
                <xsl:value-of select="//ROW[$row.id]/dr._A/DATA[$data.id]"/>
            </dr._A>            
        </ROW>      
    </xsl:template>

    <xsl:template match="/">
        <!--desired name of root node-->
        <TABLE_B>        
            <xsl:for-each select="//anamnese">
                <!--get recordId number-->                                
                <xsl:variable name="var.rec.id" select="../@RECORDID"/>
                <!--get row position number-->
                <xsl:variable name="var.row.id" select="position()"/>
                <xsl:choose>
                    <!--check if DATA block exists-->
                    <xsl:when test="DATA">
                        <xsl:for-each select="DATA">
                            <xsl:call-template name="row">
                                <xsl:with-param name="rec.id" select="$var.rec.id"/>
                                <xsl:with-param name="row.id" select="$var.row.id"/>
                                <xsl:with-param name="data.id" select="position()"/>
                            </xsl:call-template>
                        </xsl:for-each>                    
                    </xsl:when>
                    <!--proceed if DATA block does not exist-->
                    <xsl:otherwise>
                        <xsl:call-template name="row">
                            <xsl:with-param name="rec.id" select="$var.rec.id"/>
                            <xsl:with-param name="row.id" select="$var.row.id"/>
                        </xsl:call-template>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
        </TABLE_B>       
    </xsl:template>
</xsl:stylesheet>

然后使用您的输入XML尝试它,结果将是所需的:

<?xml version="1.0" encoding="UTF-8"?>
<TABLE_B>
    <ROW>
        <recordId>1801</recordId>
        <anamnese>Gevonden in lat decubitus. Dag van huis weggeweest. Vanmorgen nog goed gegeten.</anamnese>
        <diagnose/>
        <fichenr.>3607</fichenr.>
        <vis>25/08/2017</vis>
        <dr._A>EL</dr._A>
    </ROW>
    <ROW>
        <recordId>1802</recordId>
        <anamnese>zeer agressief geworden op korte tijd</anamnese>
        <diagnose> euthanasie</diagnose>
        <fichenr.>3989</fichenr.>
        <vis>2/11/2017</vis>
        <dr._A>EL</dr._A>
    </ROW>
    <ROW>
        <recordId>1802</recordId>
        <anamnese/>
        <diagnose/>
        <fichenr.>3688</fichenr.>
        <vis>6/09/2017</vis>
        <dr._A>EL</dr._A>
    </ROW>
    <ROW>
        <recordId>1802</recordId>
        <anamnese>detartratie nodig. Eerst cardiologisch onderzoek gehad bij Valerie Bavegems. Verslag volgt nog. Drinkt redelijk veel, 500 g afgevallen</anamnese>
        <diagnose/>
        <fichenr.>3608</fichenr.>
        <vis>26/08/2017</vis>
        <dr._A>MA</dr._A>
    </ROW>
    <ROW>
        <recordId>1803</recordId>
        <anamnese/>
        <diagnose/>
        <fichenr./>
        <vis/>
        <dr._A/>
    </ROW>
</TABLE_B> 

0
投票

这可能对你有所帮助。

<xsl:template match="TABLE">
  <xsl:element name="TABLE_B">
    <xsl:apply-templates select="ROW"/>
  </xsl:element>
</xsl:template>

<xsl:template match="ROW">
  <xsl:apply-templates select="anamnese">
    <xsl:with-param name="RECORDID" select="@RECORDID"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="anamnese">
  <xsl:param name="RECORDID"/>
  <xsl:apply-templates select="DATA">
    <xsl:with-param name="RECORDID" select="$RECORDID"/>
  </xsl:apply-templates>

  <xsl:if test="not(DATA)">
    <xsl:element name="ROW">
      <xsl:element name="recordId">
        <xsl:value-of select="$RECORDID"/>
      </xsl:element>

      <xsl:element name="anamnese">
        <xsl:value-of select="text()"/>
      </xsl:element>

      <xsl:apply-templates select="following-sibling::*"/>

    </xsl:element>
  </xsl:if>
</xsl:template>

<xsl:template match="DATA">
  <xsl:param name="RECORDID"/>
  <xsl:variable name="position" select="position()"/>

  <xsl:element name="ROW">
    <xsl:element name="recordId">
      <xsl:value-of select="$RECORDID"/>
    </xsl:element>

    <xsl:element name="anamnese">
      <xsl:value-of select="text()"/>
    </xsl:element>

    <xsl:element name="diagnose">
      <xsl:value-of select="../../diagnose/DATA[$position]"/>
    </xsl:element>

    <xsl:element name="fichenr.">
      <xsl:value-of select="../../fichenr./DATA[$position]"/>
    </xsl:element>

    <xsl:element name="vis">
      <xsl:value-of select="../../vis/DATA[$position]"/>
    </xsl:element>

    <xsl:element name="dr._A">
      <xsl:value-of select="../../dr._A/DATA[$position]"/>
    </xsl:element>

  </xsl:element>
</xsl:template>


<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>
© www.soinside.com 2019 - 2024. All rights reserved.