XSL变换 - 有条件地删除空标签



我有XSL可以删除所有空标签,但是如果该部分的所有标签都是空的,我只想删除空标签。例如,查看我的输入文件:

<NEWORDER>
<ID>1</ID>
<HEADER>
   <NMP>NAME PLATE</NMP>
   <ORDER>
     <USER_ID>USER ID</USER_ID>
     <PARTNER_ID>PARTNER ID</PARTNER_ID>
     <USER_REFERENCE>5555-55555555-5555</USER_REFERENCE>
     <PO_HEADER>
        <PO_NUMBER>5555-55555555-5555</PO_NUMBER>
        <PO_DATE>20170322</PO_DATE>
        <PO_TYPE>BT</PO_TYPE>
        <RELEASE_NBR></RELEASE_NBR>
        <CUST_ORDER_NBR>5555555555</CUST_ORDER_NBR>
        <CONTACT_NAME></CONTACT_NAME>
        <CONTACT_PHONE></CONTACT_PHONE>
        <TRANS_METHOD></TRANS_METHOD>
        <SHIP_COMP>SC</SHIP_COMP>
        <CURR_CODE>USD</CURR_CODE>
        <INCO_TERMS>FOB</INCO_TERMS>
        <NAMED_PLACE></NAMED_PLACE>
        <PAYMENT_METHOD>BT</PAYMENT_METHOD>
        <TERM_TYPE>555</TERM_TYPE>
        <TERM_DESC>NET 10 DAYS</TERM_DESC>
        <DEST_BRANCH>5555</DEST_BRANCH>
    </PO_HEADER>
    <PO_HEADER_NOTES>
      <TEXT1_QUAL></TEXT1_QUAL>
      <TEXT1_MSG></TEXT1_MSG>
    </PO_HEADER_NOTES>
  </ORDER>
 </HEADER>
</NEWORDER>

在此示例中,我希望输出仅删除" po_header_notes"部分,因为所有内部标签都是空的。预期输出的示例:

<NEWORDER>
<ID>1</ID>
<HEADER>
   <NMP>NAME PLATE</NMP>
   <ORDER>
     <USER_ID>USER ID</USER_ID>
     <PARTNER_ID>PARTNER ID</PARTNER_ID>
     <USER_REFERENCE>5555-55555555-5555</USER_REFERENCE>
     <PO_HEADER>
        <PO_NUMBER>5555-55555555-5555</PO_NUMBER>
        <PO_DATE>20170322</PO_DATE>
        <PO_TYPE>BT</PO_TYPE>
        <RELEASE_NBR></RELEASE_NBR>
        <CUST_ORDER_NBR>5555555555</CUST_ORDER_NBR>
        <CONTACT_NAME></CONTACT_NAME>
        <CONTACT_PHONE></CONTACT_PHONE>
        <TRANS_METHOD></TRANS_METHOD>
        <SHIP_COMP>SC</SHIP_COMP>
        <CURR_CODE>USD</CURR_CODE>
        <INCO_TERMS>FOB</INCO_TERMS>
        <NAMED_PLACE></NAMED_PLACE>
        <PAYMENT_METHOD>BT</PAYMENT_METHOD>
        <TERM_TYPE>555</TERM_TYPE>
        <TERM_DESC>NET 10 DAYS</TERM_DESC>
        <DEST_BRANCH>5555</DEST_BRANCH>
    </PO_HEADER>
  </ORDER>
 </HEADER>
</NEWORDER>

我用来删除所有空节点的XSL如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
version="1.0">
    <xsl:strip-space elements="*"/>
    <xsl:template match="*">
    <xsl:if test=". != '' or ./@* != ''">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@* | node()" />
        </xsl:element>
    </xsl:if>
    </xsl:template>
   <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="." />
        </xsl:attribute>
   </xsl:template>
       <xsl:template match="text() | comment() | processing-instruction()">
       <xsl:copy />
    </xsl:template>
</xsl:stylesheet>

请建议。任何帮助都将不胜感激。

我只想删除该部分的所有标签 空。

这不是很明显的要求。从给定的示例中看,看起来应该重述为:删除(a(有孩子的任何元素,但是(b(不包含任何文本节点 - 无论是直接的孩子,还是其后代之一的孩子。这将被实现为:

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="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="*[* and not(descendant::text())]"/>
</xsl:stylesheet>

结果

<?xml version="1.0" encoding="UTF-8"?>
<NEWORDER>
  <ID>1</ID>
  <HEADER>
    <NMP>NAME PLATE</NMP>
    <ORDER>
      <USER_ID>USER ID</USER_ID>
      <PARTNER_ID>PARTNER ID</PARTNER_ID>
      <USER_REFERENCE>5555-55555555-5555</USER_REFERENCE>
      <PO_HEADER>
        <PO_NUMBER>5555-55555555-5555</PO_NUMBER>
        <PO_DATE>20170322</PO_DATE>
        <PO_TYPE>BT</PO_TYPE>
        <RELEASE_NBR/>
        <CUST_ORDER_NBR>5555555555</CUST_ORDER_NBR>
        <CONTACT_NAME/>
        <CONTACT_PHONE/>
        <TRANS_METHOD/>
        <SHIP_COMP>SC</SHIP_COMP>
        <CURR_CODE>USD</CURR_CODE>
        <INCO_TERMS>FOB</INCO_TERMS>
        <NAMED_PLACE/>
        <PAYMENT_METHOD>BT</PAYMENT_METHOD>
        <TERM_TYPE>555</TERM_TYPE>
        <TERM_DESC>NET 10 DAYS</TERM_DESC>
        <DEST_BRANCH>5555</DEST_BRANCH>
      </PO_HEADER>
    </ORDER>
  </HEADER>
</NEWORDER>

鉴于您的要求,以下单个模板似乎适合账单:

  • 用文本或属性复制元素。
  • 对于没有文本或属性的元素:
    • 如果他们没有自己的孩子,请复制他们。
    • 如果他们有孩子,请删除它们,但孩子也没有文字或属性。

请注意,这与您的示例XSLT略有不同 - 对于属性,只有当元素的属性评估为 ''(空字符串(时才检查。根据我自己的经验,我(很少(遇到了元素可能具有空弦属性以及需要维护该属性的情况,因此,下面的代码通过检查存在属性,而不仅仅是属性的 value 。调整以符合您的要求。

<xsl:template match="*">
    <xsl:choose>
        <!-- Strip only if:
            1) Element has children.
            2) Nothing in the tree starting here contains any text or attributes. -->
        <xsl:when test="./* and not(descendant-or-self::*[text() or @*])"/>
        <!-- In all other cases, just copy over, and process children. -->
        <xsl:otherwise>
            <!-- Copies the element itself. -->
            <xsl:copy>
                <!-- Copies all attributes, if there are any. -->
                <xsl:copy-of select="@*"/>
                <!-- Sends any children along for further processing. -->
                <xsl:apply-templates/>
            </xsl:copy>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

最新更新