使用 XSLT 1.0 选择同级记录,直到下一个标记



我有以下输入XML。连续E_Records是可选的,应填充到L_Record中。我编写了下面的 XSLT 编码。我应该做任何更改吗?

输入 XML

<?xml version="1.0" encoding="UTF-8"?>
<Record>
<H_Record>
<Rec_Type>H</Rec_Type>
</H_Record>
<C_Record>
<Rec_Type>C</Rec_Type>
</C_Record>
<L_Record>
<Rec_Type>L</Rec_Type>
<L_Level>2</L_Level>
</L_Record>
<E_Record>
<Rec_Type>E</Rec_Type>
<E_Qty>3</E_Qty>
</E_Record>
<E_Record>
<Rec_Type>E</Rec_Type>
<E_Qty>4</E_Qty>
</E_Record>
<L_Record>
<Rec_Type>L</Rec_Type>
<L_Level>2</L_Level>
</L_Record>
<R_Record>
<Rec_Type>R</Rec_Type>
</R_Record>
</Record>
<Record>
<H_Record>
<Rec_Type>H</Rec_Type>
</H_Record>
<C_Record>
<Rec_Type>C</Rec_Type>
</C_Record>
<L_Record>
<Rec_Type>L</Rec_Type>
<L_Level>2</L_Level>
</L_Record>
<L_Record>
<Rec_Type>L</Rec_Type>
<L_Level>2</L_Level>
</L_Record>
<E_Record>
<Rec_Type>E</Rec_Type>
<E_Qty>1</E_Qty>
</E_Record>
<E_Record>
<Rec_Type>E</Rec_Type>
<E_Qty>2</E_Qty>
</E_Record>
<L_Record>
<Rec_Type>L</Rec_Type>
<L_Level>2</L_Level>
</L_Record>
<E_Record>
<Rec_Type>E</Rec_Type>
<E_Qty>5</E_Qty>
</E_Record>
<E_Record>
<Rec_Type>E</Rec_Type>
<E_Qty>6</E_Qty>
</E_Record>
<R_Record>
<Rec_Type>R</Rec_Type>
</R_Record>
</Record>

我期待的输出 XML 是

<Record>
<H_Record>
<Rec_Type>H</Rec_Type>
</H_Record>
<C_Record>
<Rec_Type>C</Rec_Type>
</C_Record>
<L_Record>
<Rec_Type>L</Rec_Type>
<L_Level>2</L_Level>
<E_Record>
<Rec_Type>E</Rec_Type>
<E_Qty>3</E_Qty>
</E_Record>
<E_Record>
<Rec_Type>E</Rec_Type>
<E_Qty>4</E_Qty>
</E_Record>
</L_Record>
<L_Record>
<Rec_Type>L</Rec_Type>
<L_Level>2</L_Level>
</L_Record>
<R_Record>
<Rec_Type>R</Rec_Type>
</R_Record>
</Record>
<Record>
<H_Record>
<Rec_Type>H</Rec_Type>
</H_Record>
<C_Record>
<Rec_Type>C</Rec_Type>
</C_Record>
<L_Record>
<Rec_Type>L</Rec_Type>
<L_Level>2</L_Level>
</L_Record>
<L_Record>
<Rec_Type>L</Rec_Type>
<L_Level>2</L_Level>      
<E_Record>
<Rec_Type>E</Rec_Type>
<E_Qty>1</E_Qty>
</E_Record>
<E_Record>
<Rec_Type>E</Rec_Type>
<E_Qty>2</E_Qty>
</E_Record>
</L_Record>
<L_Record>
<Rec_Type>L</Rec_Type>
<L_Level>2</L_Level>      
<E_Record>
<Rec_Type>E</Rec_Type>
<E_Qty>5</E_Qty>
</E_Record>
<E_Record>
<Rec_Type>E</Rec_Type>
<E_Qty>6</E_Qty>
</E_Record>
</L_Record>
<R_Record>
<Rec_Type>R</Rec_Type>
</R_Record>
</Record>

我已经为此编写了 XSLT 映射,如下所示,但我没有得到所需的输出。你能帮我吗?

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Record/L_Record">
<L_Record>
<xsl:variable name="header" select="."/>
<xsl:apply-templates/>
<xsl:if test = "not(following-sibling::L_Record)">
<xsl:for-each select="following-sibling::E_Record[preceding-sibling::L_Record = $header]">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:if>
</L_Record> 
</xsl:template>
</xsl:stylesheet>

请帮我这个?
当我执行上述代码时,记录 1 工作正常,但记录 2 无法正常工作。电子记录段未显示在 L 记录段中。

嗨,请测试此代码:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="L_Record">
<xsl:copy>
<xsl:apply-templates/>
<xsl:if test="following-sibling::*[1][self::E_Record]">
<xsl:call-template name="Next_E_Record">
<xsl:with-param name="next" select="following-sibling::*[1][self::E_Record]"></xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:copy>
</xsl:template>
<xsl:template name="Next_E_Record">
<xsl:param name="next"/>
<xsl:copy-of select="$next"/>
<xsl:if test="$next/following-sibling::*[1][self::E_Record]">
<xsl:call-template name="Next_E_Record">
<xsl:with-param name="next" select="$next/following-sibling::*[1][self::E_Record]"></xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="E_Record"/>

</xsl:stylesheet>

请参阅转换 https://xsltfiddle.liberty-development.net/bFWRApe

一种方法是遍历record的孩子,直到找到一个L_Record然后添加兄弟姐妹,直到找到另一个L_Record

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Record">
<Record>
<xsl:for-each select='*'>
<xsl:choose>
<xsl:when test='name()="E_Record"'/>
<xsl:when test='name()="L_Record"'>
<L_Record>
<xsl:copy-of select="*"/>
<xsl:call-template name='next'>
<xsl:with-param name='current_L' select='.'/>
<xsl:with-param name='remainder' select='following-sibling::*'/>
</xsl:call-template>
</L_Record>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</Record>
</xsl:template>
<xsl:template name='next'>
<xsl:param name='current_L'/>
<xsl:param name='remainder'/>
<xsl:param name='first' select='$remainder[1]'/>
<xsl:if test='$remainder and not(name($first)="L_Record")'>
<xsl:copy-of select="$first"/>
<xsl:call-template name='next'>
<xsl:with-param name='current_L' select='$current_L'/>
<xsl:with-param name='remainder' select='$remainder[position() &gt; 1]'/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

您应该能够创建一个 xsl:key 匹配E_Record元素,并使用前面第一个L_Record同级的生成 id 作为键。

然后,您可以匹配L_Record元素并使用匹配键复制节点集。

例。。。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="e_recs" match="E_Record" use="generate-id(preceding-sibling::L_Record[1])"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="L_Record">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:copy-of select="key('e_recs',generate-id())"/>
</xsl:copy>
</xsl:template>
<xsl:template match="E_Record"/>
</xsl:stylesheet>

小提琴:http://xsltfiddle.liberty-development.net/94Acsmd

相关内容

  • 没有找到相关文章

最新更新