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

时间:2016-07-03 07:06:56

标签: xml string xslt xml-parsing xslt-2.0

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

注意 OrderDetail 正在此处重复节点。

方案

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

INPUT 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 For Transformation:

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>

2 个答案:

答案 0 :(得分:1)

要转换示例输入,您只需要在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>

该模板仅适用于没有内容的StockCodes。由于这是唯一的模板,所有其他节点在输出中将保持相同(由于身份模板)。 匹配模板将计算所有以前的空库存节点,并将其用作索引以查找描述的标记化文本。

答案 1 :(得分:1)

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

<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>