当在节点集中找到多个相同的键时形成节点结构的问题
Issue in forming node structure when multiple identical keys found in a nodeset
场景一:L节点有子节点SL
场景二:L节点没有子节点SL
场景3:L节点有子节点SL并且有多个属性ref相同的pit元素。
如果在 和 等其他节点上找到文本“L1”(),我需要形成多个 L 节点。 SL 节点的 Id 属性(即 )是使用 中的“L1”形成的。坑节点(即)的 ref 属性也是使用“L1”形成的,我需要检查“L1”是否存在于 SL 的 id 属性或坑的 ref 属性中,并形成所需的输出。
输入xml如下
<root>
<L Id="L1">
<test>ed</test>
<SL id="L1S1">
<check>
<AId>1</AId>
</check>
<MD>
<UnitNumber>1</UnitNumber>
</MD>
</SL>
<SL id="L1S2">
<check>
<AId>2</AId>
</check>
<MD>
<UnitNumber>2</UnitNumber>
</MD>
</SL>
</L>
<cp>
<current>
<Amt>20154.00</Amt>
</current>
<pi>
<pit ref="L1S1">
<value>123</value>
</pit>
<pit ref="L1S2">
<value>1232</value>
</pit>
</pi>
</cp>
</root>
预期输出应为:
<root>
<L Id="L1">
<SL id="L1S1">
<check>
<AId>1</AId>
</check>
<MD>
<UnitNumber>1</UnitNumber>
</MD>
</SL>
<pit ref="L1S1">
<value>123</value>
</pit>
</L>
<L Id="L1">
<SL id="L1S2">
<check>
<AId>2</AId>
</check>
<MD>
<UnitNumber>2</UnitNumber>
</MD>
</SL>
<pit ref="L1S2">
<value>1232</value>
</pit>
</L>
</root>
<root>
<L Id="L1">
<test>ed</test>
</L>
<cp>
<current>
<Amt>20154.00</Amt>
</current>
<pi>
<pit ref="L1S1">
<value>123</value>
</pit>
<pit ref="L1S2">
<value>1232</value>
</pit>
</pi>
</cp>
</root>
预期输出应为:
<root>
<L Id="L1">
<pit ref="L1S1">
<value>123</value>
</pit>
</L>
<L Id="L1">
<pit ref="L1S2">
<value>1232</value>
</pit>
</L>
</root>
场景 3:
输入xml如下
<root>
<L Id="L1">
<test>ed</test>
<SL id="L1S1">
<check>
<AId>1</AId>
</check>
<MD>
<UnitNumber>1</UnitNumber>
</MD>
</SL>
<SL id="L1S2">
<check>
<AId>2</AId>
</check>
<MD>
<UnitNumber>2</UnitNumber>
</MD>
</SL>
</L>
<cp>
<current>
<Amt>20154.00</Amt>
</current>
<pi>
<pit ref="L1S1">
<value>123</value>
</pit>
<pit ref="L1S1">
<value>234</value>
</pit>
<pit ref="L1S2">
<value>1232</value>
</pit>
<pit ref="L1S2">
<value>1</value>
</pit>
</pi>
</cp>
</root>
预期输出应为:
<root>
<L Id="L1">
<SL id="L1S1">
<check>
<AId>1</AId>
</check>
<MD>
<UnitNumber>1</UnitNumber>
</MD>
</SL>
<pit ref="L1S1">
<value>123</value>
</pit>
</L>
<L Id="L1">
<SL id="L1S1">
<check>
<AId>1</AId>
</check>
<MD>
<UnitNumber>1</UnitNumber>
</MD>
</SL>
<pit ref="L1S1">
<value>234</value>
</pit>
</L>
<L Id="L1">
<SL id="L1S2">
<check>
<AId>2</AId>
</check>
<MD>
<UnitNumber>2</UnitNumber>
</MD>
</SL>
<pit ref="L1S2">
<value>1232</value>
</pit>
</L>
<L Id="L1">
<SL id="L1S2">
<check>
<AId>2</AId>
</check>
<MD>
<UnitNumber>2</UnitNumber>
</MD>
</SL>
<pit ref="L1S2">
<value>1</value>
</pit>
</L>
</root>
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="pit-SL" match="pit" use="@ref" />
<xsl:key name="pit-L" match="pit" use="substring(@ref,1,2)" />
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="L[SL]">
<xsl:apply-templates select="SL"/>
</xsl:template>
<xsl:template match="SL">
<L>
<xsl:copy-of select="parent::L/@Id"/>
<xsl:copy>
<xsl:copy-of select="@id"/>
<xsl:apply-templates select="node()"/>
<xsl:copy-of select="key('pit-SL',@id)"/>
</xsl:copy>
</L>
</xsl:template>
<xsl:template match="L[not(SL)]">
<xsl:apply-templates select="key('pit-L',@Id)">
<xsl:with-param name="L" select="."/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="pit">
<xsl:param name="L"/>
<L>
<xsl:copy-of select="$L/@Id"/>
<xsl:copy-of select="."/>
</L>
</xsl:template>
<xsl:template match="cp"/>
</xsl:stylesheet>
我在第 3 种情况下遇到问题,当有多个相同的 pit ref 键时。
这是一个方法。
<xsl:key name="SLkey" match="SL" use="@id"/>
<xsl:key name="pitKey" match="pit" use="generate-id()"/>
<xsl:template match="root">
<xsl:copy>
<xsl:apply-templates select="@*|.//pit"/>
</xsl:copy>
</xsl:template>
<xsl:template match="pit">
<xsl:choose>
<!-- Is there an SL node match? -->
<xsl:when test="key('SLkey', @ref)[1]">
<xsl:apply-templates select="key('SLkey', @ref)[1]/.." mode="Loutput">
<xsl:with-param name="ref" select="@ref"/>
<xsl:with-param name="pitID" select="generate-id(.)"/>
</xsl:apply-templates>
</xsl:when>
<!-- Use the first L in the document. -->
<xsl:otherwise>
<xsl:apply-templates select="//L[1]" mode="Loutput">
<xsl:with-param name="ref" select="@ref"/>
<xsl:with-param name="pitID" select="generate-id(.)"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- ********************** -->
<!-- Loutput mode templates -->
<!-- ********************** -->
<xsl:template match="node()|@*" mode="Loutput">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="Loutput"/>
</xsl:copy>
</xsl:template>
<xsl:template match="L" mode="Loutput">
<xsl:param name="ref"/>
<xsl:param name="pitID"/>
<xsl:copy>
<xsl:apply-templates select="@*|SL[@id = $ref]" mode="Loutput"/>
<xsl:apply-templates select="key('pitKey', $pitID)" mode="Loutput"/>
</xsl:copy>
</xsl:template>
场景一:L节点有子节点SL 场景二:L节点没有子节点SL 场景3:L节点有子节点SL并且有多个属性ref相同的pit元素。 如果在 和 等其他节点上找到文本“L1”(),我需要形成多个 L 节点。 SL 节点的 Id 属性(即 )是使用 中的“L1”形成的。坑节点(即)的 ref 属性也是使用“L1”形成的,我需要检查“L1”是否存在于 SL 的 id 属性或坑的 ref 属性中,并形成所需的输出。
输入xml如下
<root>
<L Id="L1">
<test>ed</test>
<SL id="L1S1">
<check>
<AId>1</AId>
</check>
<MD>
<UnitNumber>1</UnitNumber>
</MD>
</SL>
<SL id="L1S2">
<check>
<AId>2</AId>
</check>
<MD>
<UnitNumber>2</UnitNumber>
</MD>
</SL>
</L>
<cp>
<current>
<Amt>20154.00</Amt>
</current>
<pi>
<pit ref="L1S1">
<value>123</value>
</pit>
<pit ref="L1S2">
<value>1232</value>
</pit>
</pi>
</cp>
</root>
预期输出应为:
<root>
<L Id="L1">
<SL id="L1S1">
<check>
<AId>1</AId>
</check>
<MD>
<UnitNumber>1</UnitNumber>
</MD>
</SL>
<pit ref="L1S1">
<value>123</value>
</pit>
</L>
<L Id="L1">
<SL id="L1S2">
<check>
<AId>2</AId>
</check>
<MD>
<UnitNumber>2</UnitNumber>
</MD>
</SL>
<pit ref="L1S2">
<value>1232</value>
</pit>
</L>
</root>
<root>
<L Id="L1">
<test>ed</test>
</L>
<cp>
<current>
<Amt>20154.00</Amt>
</current>
<pi>
<pit ref="L1S1">
<value>123</value>
</pit>
<pit ref="L1S2">
<value>1232</value>
</pit>
</pi>
</cp>
</root>
预期输出应为:
<root>
<L Id="L1">
<pit ref="L1S1">
<value>123</value>
</pit>
</L>
<L Id="L1">
<pit ref="L1S2">
<value>1232</value>
</pit>
</L>
</root>
场景 3: 输入xml如下
<root>
<L Id="L1">
<test>ed</test>
<SL id="L1S1">
<check>
<AId>1</AId>
</check>
<MD>
<UnitNumber>1</UnitNumber>
</MD>
</SL>
<SL id="L1S2">
<check>
<AId>2</AId>
</check>
<MD>
<UnitNumber>2</UnitNumber>
</MD>
</SL>
</L>
<cp>
<current>
<Amt>20154.00</Amt>
</current>
<pi>
<pit ref="L1S1">
<value>123</value>
</pit>
<pit ref="L1S1">
<value>234</value>
</pit>
<pit ref="L1S2">
<value>1232</value>
</pit>
<pit ref="L1S2">
<value>1</value>
</pit>
</pi>
</cp>
</root>
预期输出应为:
<root>
<L Id="L1">
<SL id="L1S1">
<check>
<AId>1</AId>
</check>
<MD>
<UnitNumber>1</UnitNumber>
</MD>
</SL>
<pit ref="L1S1">
<value>123</value>
</pit>
</L>
<L Id="L1">
<SL id="L1S1">
<check>
<AId>1</AId>
</check>
<MD>
<UnitNumber>1</UnitNumber>
</MD>
</SL>
<pit ref="L1S1">
<value>234</value>
</pit>
</L>
<L Id="L1">
<SL id="L1S2">
<check>
<AId>2</AId>
</check>
<MD>
<UnitNumber>2</UnitNumber>
</MD>
</SL>
<pit ref="L1S2">
<value>1232</value>
</pit>
</L>
<L Id="L1">
<SL id="L1S2">
<check>
<AId>2</AId>
</check>
<MD>
<UnitNumber>2</UnitNumber>
</MD>
</SL>
<pit ref="L1S2">
<value>1</value>
</pit>
</L>
</root>
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="pit-SL" match="pit" use="@ref" />
<xsl:key name="pit-L" match="pit" use="substring(@ref,1,2)" />
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="L[SL]">
<xsl:apply-templates select="SL"/>
</xsl:template>
<xsl:template match="SL">
<L>
<xsl:copy-of select="parent::L/@Id"/>
<xsl:copy>
<xsl:copy-of select="@id"/>
<xsl:apply-templates select="node()"/>
<xsl:copy-of select="key('pit-SL',@id)"/>
</xsl:copy>
</L>
</xsl:template>
<xsl:template match="L[not(SL)]">
<xsl:apply-templates select="key('pit-L',@Id)">
<xsl:with-param name="L" select="."/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="pit">
<xsl:param name="L"/>
<L>
<xsl:copy-of select="$L/@Id"/>
<xsl:copy-of select="."/>
</L>
</xsl:template>
<xsl:template match="cp"/>
</xsl:stylesheet>
我在第 3 种情况下遇到问题,当有多个相同的 pit ref 键时。
这是一个方法。
<xsl:key name="SLkey" match="SL" use="@id"/>
<xsl:key name="pitKey" match="pit" use="generate-id()"/>
<xsl:template match="root">
<xsl:copy>
<xsl:apply-templates select="@*|.//pit"/>
</xsl:copy>
</xsl:template>
<xsl:template match="pit">
<xsl:choose>
<!-- Is there an SL node match? -->
<xsl:when test="key('SLkey', @ref)[1]">
<xsl:apply-templates select="key('SLkey', @ref)[1]/.." mode="Loutput">
<xsl:with-param name="ref" select="@ref"/>
<xsl:with-param name="pitID" select="generate-id(.)"/>
</xsl:apply-templates>
</xsl:when>
<!-- Use the first L in the document. -->
<xsl:otherwise>
<xsl:apply-templates select="//L[1]" mode="Loutput">
<xsl:with-param name="ref" select="@ref"/>
<xsl:with-param name="pitID" select="generate-id(.)"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- ********************** -->
<!-- Loutput mode templates -->
<!-- ********************** -->
<xsl:template match="node()|@*" mode="Loutput">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="Loutput"/>
</xsl:copy>
</xsl:template>
<xsl:template match="L" mode="Loutput">
<xsl:param name="ref"/>
<xsl:param name="pitID"/>
<xsl:copy>
<xsl:apply-templates select="@*|SL[@id = $ref]" mode="Loutput"/>
<xsl:apply-templates select="key('pitKey', $pitID)" mode="Loutput"/>
</xsl:copy>
</xsl:template>