【问题标题】:XSLT :Condition for check if null and empty element then only assign value to other elementXSLT:检查是否为空元素和空元素的条件,然后仅将值分配给其他元素
【发布时间】:2016-07-03 07:06:55
【问题描述】:

我们输入了 XML。其中,对于许多行项目(OrderLineID 元素),StockCode 元素是空的。对于 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 元素为空”? &lt;StockCode&gt;Nil&lt;/StockCode&gt; 是空元素吗?
  • 感谢您的关注,我刚刚更正了问题 Nil 替换为
  • 您的输入有 5 个 StockLine 和 Nill StockCode - 您的输出有 7 个 StockLine - 每行描述一个加上另一个突然出现的行。评论(或者是评论)节点随机出现。这个问题是 michael.hor257k 昨天回答的类似问题的扩展。但 Michaels anwser 的 xml 质量更好!您能否提供更清晰的输入和输出 xml 示例。

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


【解决方案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>

【讨论】:

  • 应用给定 XSLT: 应该拆分为 而不是 这里是 XSLT xsltransform.net/pPzifqt 之后的附加输出
  • 我的问题是这个问题的延伸:stackoverflow.com/questions/38156641/…
  • 一切看起来都不错,只有 StockCode 值应属于 Comment 元素,而 StockCode 应保持为空值。
  • 好吧,在你的问题中你已经描述了你想要的输出,它显示了&lt;StockCode&gt;EDIORDER-SAVE COMMENTS&lt;/StockCode&gt;,它没有显示任何新的Comment 元素。
  • 很抱歉给您带来不便。这是我的大错。打算改正。
【解决方案2】:

要转换您的示例输入,您只需在 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 节点,并将其用作索引来定位描述的标记化文本。

【讨论】:

  • 感谢您给我解决方案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-14
  • 2012-08-28
  • 1970-01-01
  • 2011-04-14
相关资源
最近更新 更多