XSLT:检查空元素是否为空然后只将值赋给其他元素的条件

XSLT :Condition for check if null and empty element then only assign value to other element

我们输入 XML.In,StockCode 元素对于许多订单项(OrderLineID 元素)为空。对于 XML 中的所有空 StockCode 元素,必须有 Comment 元素值。同样,对于所有此类空 Comment 元素,必须存在 StockCode 值。

注意 : OrderDetail 在这里重复节点。

场景:

我们必须拆分 OrderDescription 字符串。这样它总是寻找空的 StockCode 元素。然后仅将拆分字符串值分配给 Comment 元素。否则,对于所有具有值的 StockCode,不应将拆分字符串分配给 Comment Element

输入 XML :

<SalesOrders xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xsd:noNamespaceSchemaLocation="SORTOIDOC.XSD">
      <Orders>
        <OrderHeader>
          <Customer>000016</Customer>
          <OrderDate>2016-04-19</OrderDate>
          <SalesForceOrderNumber>ORD-411324</SalesForceOrderNumber>
        </OrderHeader>
        <OrderDetails>
          <StockLine>
            <StockCode>ABB-CDE-FGH-01</StockCode>
            <OrderDescription>EDIORDER-SAVE COMMENTS
    C3 Generic
    LOC 0833
    Expected arrival 01/07/2016
     OTYPE NE
    TRKPC 01 GM/00007643020008361321</OrderDescription>
            <OrderLineID>OR-1561179</OrderLineID>
          </StockLine>
           <StockLine>
                    <StockCode>BCD-EFGH-01</StockCode>
                    <OrderLineID>OR-1561186</OrderLineID>
                    </Comment>
                  </StockLine>
          <StockLine>
            <StockCode></StockCode>
            </Comment>
            <OrderLineID>OR-1561180</OrderLineID>
          </StockLine>
          <StockLine>
            <StockCode></StockCode>
            </Comment>
            <OrderLineID>OR-1561181</OrderLineID>
          </StockLine>
          <StockLine>
            <StockCode></StockCode>
            </Comment>
            <OrderLineID>OR-1561182</OrderLineID>
          </StockLine>
          <StockLine>
            <StockCode></StockCode>
            </Comment>
            <OrderLineID>OR-1561183</OrderLineID>
          </StockLine>
          <StockLine>
            <StockCode></StockCode>
            </Comment>
            <OrderLineID>OR-1561184</OrderLineID>
          </StockLine>
           <StockLine>
            <StockCode></StockCode>
            </Comment>
            <OrderLineID>OR-1561185</OrderLineID>
          </StockLine>
        </OrderDetails>
      </Orders>
    </SalesOrders>

用于转换的现有 XSLT:

XSLT2.0

<xsl:stylesheet version="2.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="*"/>

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

    <xsl:template match="StockLine">
        <xsl:variable name="i" select="position()" />
        <xsl:copy>
            <xsl:copy-of select="StockCode"/>
            <Comment>
                <xsl:value-of select="normalize-space(tokenize(../StockLine[1]/OrderDescription, '\n')[$i])"/>
            </Comment>
            <xsl:copy-of select="OrderLineID"/>
        </xsl:copy>
    </xsl:template>

    </xsl:stylesheet>

预期输出值:

<SalesOrders xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xsd:noNamespaceSchemaLocation="SORTOIDOC.XSD">
              <Orders>
                <OrderHeader>
                  <Customer>000016</Customer>
                  <OrderDate>2016-04-19</OrderDate>
                  <SalesForceOrderNumber>ORD-411324</SalesForceOrderNumber>
                </OrderHeader>
                <OrderDetails>
                  <StockLine>
                    <StockCode>ABB-CDE-FGH-01</StockCode>
                    </Comment>
                    <OrderDescription>EDIORDER-SAVE COMMENTS
            C3 Generic
            LOC 0833
            Expected arrival 01/07/2016
             OTYPE NE
            TRKPC 01 GM/00007643020008361321</OrderDescription>
                    <OrderLineID>OR-1561179</OrderLineID>
                  </StockLine>
                   <StockLine>
                    <StockCode>BCD-EFGH-01</StockCode>
                    <OrderLineID>OR-1561186</OrderLineID>
                    </Comment>
                  </StockLine>
                  <StockLine>
                    <Comment>EDIORDER-SAVE COMMENTS</Comment>
                    </StockCode>
                    <OrderLineID>OR-1561180</OrderLineID>
                  </StockLine>
                  <StockLine>
                    <Comment>C3 Generic</Comment>
                    </StockCode>
                    <OrderLineID>OR-1561181</OrderLineID>
                  </StockLine>
                  <StockLine>
                    <Comment>LOC 0833</Comment>
                    </StockCode>
                    <OrderLineID>OR-1561182</OrderLineID>
                  </StockLine>
                  <StockLine>
                    <Comment>Expected arrival 01/07/2016</Comment>
                    </StockCode>
                    <OrderLineID>OR-1561183</OrderLineID>
                  </StockLine>
                  <StockLine>
                    <Comment> OTYPE NE</Comment>
                    </StockCode>
                    <OrderLineID>OR-1561184</OrderLineID>
                  </StockLine>
                  <StockLine>
                    <Comment>TRKPC 01 GM/00007643020008361321</Comment>
                    </StockCode>
                    <OrderLineID>OR-1561185</OrderLineID>
                  </StockLine>
                </OrderDetails>
              </Orders>
            </SalesOrders>

要转换示例输入,您只需像这样在 StockCode 节点上进行模板匹配:

<xsl:stylesheet version="2.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="*"/>

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



<xsl:template match="StockCode[not(node())]">
    <xsl:variable name="i"><xsl:number count="StockCode[not(node())]"  select="../StockCode[not(node())]"  level="any" /></xsl:variable>
    <xsl:copy>
            <xsl:value-of select="normalize-space(tokenize(ancestor::OrderDetails/StockLine[1]/OrderDescription, '\n')[number($i)])"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

该模板将只适用于没有内容的股票代码。由于这是唯一的模板,所有其他节点在输出中将保持不变(由于身份模板)。 匹配模板将计算所有先前为空的 StockCode 节点,并将其用作索引来定位描述的标记化文本。

这是我的建议,标记一次并将值作为参数传递:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="OrderDetails">
        <xsl:copy>
            <xsl:variable name="descriptions" as="xs:string*" select="tokenize(StockLine[1]/OrderDescription, '\n')"/>
            <xsl:apply-templates>
                <xsl:with-param name="descriptions" as="xs:string*" select="$descriptions" tunnel="yes"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="StockLine/StockCode[not(normalize-space())]">
        <xsl:param name="descriptions" tunnel="yes"/>
        <xsl:variable name="pos" as="xs:integer">
            <xsl:number count="StockLine[StockCode[not(normalize-space())]]"/>
        </xsl:variable>
        <xsl:copy>
            <xsl:value-of select="normalize-space($descriptions[$pos])"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

如果您想创建新的 Comment 元素而不是填充空 StockCode 元素,请使用如下方法:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="OrderDetails">
        <xsl:copy>
            <xsl:variable name="descriptions" as="xs:string*" select="tokenize(StockLine[1]/OrderDescription, '\n')"/>
            <xsl:apply-templates>
                <xsl:with-param name="descriptions" as="xs:string*" select="$descriptions"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="StockLine[StockCode[not(normalize-space())]]">
        <xsl:param name="descriptions"/>
        <xsl:variable name="pos" as="xs:integer">
            <xsl:number count="StockLine[StockCode[not(normalize-space())]]"/>
        </xsl:variable>
        <xsl:copy>
            <xsl:copy-of select="*"/>
            <Comment><xsl:value-of select="normalize-space($descriptions[$pos])"/></Comment>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>