我有这个非常大的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)
我假设节点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>
如果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>
这可能对你有所帮助。
<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>