用于在父段下插入段的 XSLT 代码

XSLT code to insert segment under parent segment

提问人:user22788171 提问时间:10/23/2023 最后编辑:Mads Hansenuser22788171 更新时间:10/24/2023 访问量:50

问:

我有一个输入 XML 文档,其中需要在父段下移动几个段,条件应该在段下仅为“8R”时。对于其他段且没有条件,只需移动到 下即可。<c><b><b2><e><f><d>

<?xml version="1.0" encoding="UTF-8"?>
<ns0:TEST_Report xmlns:ns0="urn:abc">
   <Record>
      <a>
         <a1>123</a1>
         <a2>11</a2>
      </a>
      <b>
         <b1>23</b1>
         <b2>SJ</b2>
      </b>
      <b>
         <b1>67</b1>
         <b2>8S</b2>
      </b>
      <b>
         <b1>90</b1>
         <b2>8R</b2>
      </b>
      <c>
         <c1>asd</c1>
         <c2>2342445435346</c2>
      </c>
      <c>
         <c1>wsx</c1>
         <c2>8798987978</c2>
      </c>
      <d>
         <d1>XYZ</d1>
         <d2>cvb</d2>
      </d>
      <e>
         <e1>1212</e1>
      </e>
      <e>
         <e1>4321</e1>
      </e>
      <f>
         <f1>11</f1>
         <f2>11</f2>
      </f>
      <f>
         <f1>133</f1>
         <f2>1133</f2>
      </f>
      <f>
         <f1>1345</f1>
         <f2>54434</f2>
      </f>
      <d>
         <d1>XYZ</d1>
         <d2>cvb</d2>
      </d>
      <e>
         <e1>1212</e1>
      </e>
      <f>
         <f1>11</f1>
         <f2>11</f2>
      </f>
      <f>
         <f1>133</f1>
         <f2>1133</f2>
      </f>
   </Record>
</ns0:TEST_Report>

我试过的 XSLT 代码:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="urn:abc">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="TEST_Report">
        <ns0:TEST_Report>
            <xsl:apply-templates select="@*|node()"/>
        </ns0:TEST_Report>
    </xsl:template>
    <xsl:template match="B">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
            <xsl:apply-templates select="following-sibling::C[1]"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="C">
        <xsl:if test="preceding-sibling::B[3]">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

所需输出:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:TEST_Report xmlns:ns0="urn:abc">
   <Record>
      <a>
         <a1>123</a1>
         <a2>11</a2>
      </a>
      <b>
         <b1>23</b1>
         <b2>SJ</b2>
      </b>
      <b>
         <b1>67</b1>
         <b2>8S</b2>
      </b>
      <b>
         <b1>90</b1>
         <b2>8R</b2>
         <c>
            <c1>asd</c1>
            <c2>2342445435346</c2>
         </c>
         <c>
            <c1>wsx</c1>
            <c2>8798987978</c2>
         </c>
      </b>
      <d>
         <d1>XYZ</d1>
         <d2>cvb</d2>
         <e>
            <e1>1212</e1>
         </e>
         <e>
            <e1>4321</e1>
         </e>
         <f>
            <f1>11</f1>
            <f2>11</f2>
         </f>
         <f>
            <f1>133</f1>
            <f2>1133</f2>
         </f>
         <f>
            <f1>1345</f1>
            <f2>54434</f2>
         </f>
      </d>
      <d>
         <d1>XYZ</d1>
         <d2>cvb</d2>
         <e>
            <e1>1212</e1>
         </e>
         <f>
            <f1>11</f1>
            <f2>11</f2>
         </f>
         <f>
            <f1>133</f1>
            <f2>1133</f2>
         </f>
      </d>
   </Record>
</ns0:TEST_Report>

请使用 xslt 1.0 代码帮助实现此目的。我也尝试了其他一些代码,但它不适用于此要求。

XML XSLT XSLT-1.0

评论

1赞 Mads Hansen 10/23/2023
XPath 区分大小写。您显示的是小写元素,但您的匹配表达式匹配的是大写元素,因此这是一个问题。
0赞 michael.hor257k 10/23/2023
当没有元素包含元素时,输入是否可以包含元素?还是包含没有前面的元素?cb<b2>8R</b2>efd
0赞 Mads Hansen 10/23/2023
要求真的是关于有一个还是只是最后一个?b<b2>8R</b2>b
0赞 user22788171 10/24/2023
感谢您的回复 @michael.hor257k ,它对我有用!!要求是针对 8R 段的,如果没有 b 元素包含 <b2>8R</b2>,c 元素就不会出现。同样,e 和 f 元素也不会没有 d 元素。

答:

0赞 michael.hor257k 10/23/2023 #1

这比看起来要复杂得多 - 不是因为 上的条件,而是因为你有多个元素,每个元素都有自己的 和 元素的“尾巴”。bdef

从第一个的上下文来看,所有后续元素和元素都在轴上 - 无论沿途放置任何“干预”元素。所以基本上你正在寻找一个 的 XSLT 1.0 实现,它可以被处理为:deffollowing-siblingdgroup-starting-with

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="c" match="c" use="generate-id(preceding-sibling::b[b2='8R'][1])" />
<xsl:key name="ef" match="e|f" use="generate-id(preceding-sibling::d[1])" />

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="b[b2='8R']">
    <xsl:copy>
        <xsl:copy-of select="*"/>
        <xsl:copy-of select="key('c', generate-id())"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="d">
    <xsl:copy>
        <xsl:copy-of select="*"/>
        <xsl:copy-of select="key('ef', generate-id())"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="c[preceding-sibling::b[1]/b2='8R'] | e | f"/>

</xsl:stylesheet>

如果每个模板都有一个包含 的前面的同级,那么您可以将最后一个模板简化为:cb<b2>8R</b2>

<xsl:template match="c|e|f"/>