当在节点集中找到多个相同的键时形成节点结构的问题

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>