使用 XSL 转换,如何仅 return XML 需要更改的元素

Using XSL transform, how do I only return XML elements that require a change

我有一个需要使用 XSL 处理的 XLM,我的代码将几个元素连接到描述元素,但输出只需要包含已更改的元素。

现在,我的代码 returns 所有内容都已正确连接,但它还有 returns 个不需要任何更改的元素。

我的样品XML有3个项目,第一个没有任何变化所以不需要退回。 第二个在数量上发生了变化,第三个需要连接部分,所以最后两个是唯一应该返回的。

样本XML

<?xml version='1.0' encoding='UTF-8'?>
<document>
    <myObjects>
        <Base>
            <Code>11</Code>
            <Item>216</Item>
            <Build>BH</Build>
            <Quantity>203</Quantity>
            <Description>BH-203-216|Description 1</Description>
        </Base>
        
        <Base>
            <Code>19</Code>
            <Item>169</Item>
            <Build>FM</Build>
            <Quantity>2</Quantity>
            <Description>FM-201-169|Description 2</Description>
        </Base>
        
        <Base>
            <Code>20</Code>
            <Item>169</Item>
            <Build>MM</Build>
            <Quantity></Quantity>
            <Description>Description 3</Description>
        </Base>


    </myObjects>
</document>

结果 XML 应该如下所示:

<document>
   <myObjects>
      <Base>
         <Code>19</Code>
         <Description>FM-2-169|Description 2</Description>
      </Base>
      <Base>
         <Code>20</Code>
         <Description>MM-169|Description 3</Description>
      </Base>
   </myObjects>
</document>

我的 XSL 代码:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes" encoding="utf-8" media-type="xml/plain"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*"/>
        </xsl:copy>
    </xsl:template>
    
    <!-- drop elements with concat-->
    <xsl:template match="Base">
        <xsl:variable name="currentPre" select="substring-before(Description,'|')" />
        <xsl:variable name="currentPost" select="substring-after(Description,'|')" />
        <xsl:variable name="NewPre" select="string-join((Build,Quantity/text(),Item/text()), '-')" />
 
        <xsl:copy>
        
            <xsl:choose>
                <xsl:when test="not(contains(Description, '|'))">
                    <xsl:variable name="emptyDes" select="Description" />
                    <xsl:copy-of select="Code"/>
                    <Description>
                        <xsl:value-of select="string-join((Build,Quantity/text(),Item/text()), '-'), Description" separator="|"/>
                    </Description>
                </xsl:when>
                    
                <xsl:otherwise>
                    <xsl:copy-of select="Code"/>
                    <Description>
                        <xsl:value-of select="string-join((Build,Quantity/text(),Item/text()), '-'), $currentPost" separator="|"/>
                    </Description>
                </xsl:otherwise>
            </xsl:choose>

        </xsl:copy>

    </xsl:template>
</xsl:stylesheet>

如果测试新构造的Description值是否等于当前的Description值,不同时才复制,也可以合并生成那些项的逻辑:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes" encoding="utf-8" media-type="xml/plain"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*"/>
        </xsl:copy>
    </xsl:template>
    
    <!-- drop elements with concat-->
    <xsl:template match="Base">
        <xsl:variable name="currentPre" select="substring-before(Description,'|')" as="xs:string"/>
        <xsl:variable name="currentPost" select="substring-after(Description,'|')[normalize-space()]" as="xs:string?" />
        <xsl:variable name="NewPost" select="($currentPost,Description)[1]"/>
        <xsl:variable name="NewPre" select="string-join((Build,Quantity/text(),Item/text()), '-')" />
        <xsl:variable name="NewDescription" select="string-join(($NewPre, $NewPost), '|')"/>
        <xsl:if test="not(Description eq $NewDescription)">
            <xsl:copy>
                <xsl:copy-of select="Code"/>
                <Description><xsl:value-of select="$NewDescription"/></Description>
            </xsl:copy>
        </xsl:if>   
    </xsl:template>
</xsl:stylesheet>