2017-01-30 65 views
0

刪除子節點,我有以下XML:XSLT:不重複的XPath

<?xml version="1.0"?> 
<Transaction> 
    <Product> 
     <ProductRq> 
      <ContactInfo> 
       <!-- several child elements --> 
      </ContactInfo> 
      <OrderInfo> 
       <!-- several child elements --> 
      </OrderInfo> 
      <ProductInfo> 
       <!-- several child elements --> 
      </ProductInfo> 
      <AddressInfo> 
       <!-- several child elements --> 
      </AddressInfo> 
      <AuditInfo> 
       <!-- several child elements --> 
      </AuditInfo> 
      <DeliveryInfo> 
       <!-- several child elements --> 
      </DeliveryInfo> 
     </ProductRq> 
    </Product> 
</Transaction> 

爲簡潔起見,我已經離開了幾個孩子的<ProductRq>標籤,它包含4個或5個以上的子元素類似於到<OrderInfo><CustomerInfo>,以及* Info元素的子節點。

我需要刪除Order和<CustomerInfo>等元素的子元素,同時保留* Info標記。在7個標籤中,大約有4個將通過這個過程。我想不出如何不重複:

<xsl:template match="Transcation/Product/ProductRq/<tag name here>/*" /> 

<ProductRq>的每個孩子。有沒有一種方法可以利用上下文節點(<ProductRq>)和通過子節點循環的方式,從上面除去他們自己的子節點?

編輯:
我添加了<ProductRq>的其餘子標記。除<AuditInfo><ContactInfo>之外的所有標籤必須刪除其子節點。

+0

您實際上並不需要在模板匹配中指定完整的xpath,您可以在/*」/>'中執行。如果相同的元素可能出現在層次結構的不同級別中,並且您需要區分它們,則只需使用完整路徑對其進行限定即可。 –

+0

好吧,我認爲ProductRq中的一些子元素可能會對文檔中的不同標記重複一次,但ProducerRq是唯一的,因此ProducerRq/就足夠了? – jbailie1991

+0

@ jbailie1991 - 你真的需要展示那些遺漏的孩子,因爲它們與你的問題非常相關。至少展示* ProductRq *的孩子。 – Parfait

回答

1

一種解決方案是運用以下XSLT:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml"/> 

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

    <!-- skip all child nodes of ProductRq except they are AuditInfo or ContactInfo --> 
    <xsl:template match="ProductRq/*[not(self::AuditInfo | self::ContactInfo)]">  
    <xsl:element name="{name(.)}" /> <!-- so create an element with this name --> 
    </xsl:template> 

</xsl:stylesheet> 

輸出:

<?xml version="1.0"?> 
<Transaction> 
    <Product> 
     <ProductRq> 
      <ContactInfo> 
       <!-- several child elements --> 
      </ContactInfo> 
      <OrderInfo/> 
      <ProductInfo/> 
      <AddressInfo/> 
      <AuditInfo> 
       <!-- several child elements --> 
      </AuditInfo> 
      <DeliveryInfo/> 
     </ProductRq> 
    </Product> 
</Transaction> 
+0

所以第三個模板,如果我理解正確,就匹配ProductRq中不是AuditInfo或ContactInfo的子節點,那麼檢查元素名稱是否爲空,如果不是,則創建一個具有該名稱的新元素?所以或多或少用相同的標籤覆蓋匹配的元素,除了空的? – jbailie1991

+0

@ jbailie1991:你說得對。閱讀你的評論後,我也從答案中刪除了多餘的第二個模板。因此,最後一個(以前的第三個)模板只是重新創建了所有不屬於「AuditInfo」或「ContactInfo」(並且沒有其他節點類型(name()= empty))的元素,而沒有任何子節點。 – zx485

+0

啊,確實很酷。那麼這些子節點將永遠在那裏,即使是空的,所以這可能會進一步並放棄條件嗎?只需用空白版本替換每個找到的元素? – jbailie1991

0

我需要刪除的元素的孩子喜歡Order<CustomerInfo>同時保留*信息標籤。

你正在尋找模板是

<!-- XSLT 2.0 and up --> 
<xsl:template match="ProductRq/*[ends-with(name(), 'Info')]/*" /> 


<!-- XSLT 1.0 variant, as ends-with() does not exist here --> 
<xsl:template match="ProductRq/*[ 
    substring-before(name(), 'Info') != '' and substring-after(name(), 'Info') = '' 
]/*" /> 
+0

我喜歡xslt 2一個班輪,但是這將刪除以Info結尾的所有元素的所有子元素。對於我的用例,我需要保留AuditInfo和ContactInfo的子元素,並剝離其他* Info標籤的子節點。 – jbailie1991

+0

@ jbailie1991這很簡單,只需在表達式中添加例外情況,如'and not(name() ='KeepThis'或name()='KeepThat')'。 – Tomalak

+0

@ jbailie1991對我的回答有任何反饋?你有沒有嘗試過?它有用嗎?如果沒有,什麼不起作用? – Tomalak

0

編寫模板匹配ProductRq

<xsl:template match="ProductRq"> 
    <xsl:copy> 
    <xsl:apply-templates select="ContactInfo | OrderInfo | ProductInfo | AddressInfo"/> 
    </xsl:copy> 
</xsl:template> 

正如你看到的,select子句包含所有子節點,這將被包含。 默認情況下,它會執行深層複製(使用子節點)。

但是您寫道,某些節點(例如ContactInfoOrderInfo)只能在淺模式下複製。 (我認爲這種模式應該包含複製唯一的孩子文本節點 但僅此而已的「空」的標籤複製似乎是一個奇怪的概念。)

爲了讓這些節點的唯一淺拷貝,再寫tempate:

<xsl:template match="ContactInfo | OrderInfo"> 
    <xsl:copy><xsl:apply-templates select="text()"/></xsl:copy> 
</xsl:template> 

綜上所述,你寫的參與節點的名稱(用 「|」 分隔)在兩個地方:

  • 所有名稱是第一個模板,
  • 名的節點在第二個模板中被淺拷貝。

某處你必須寫這些名字。

+0

我明白了,因此我將指定第一個模板中的所有ProductRqs子節點,並定義我想從第二個模板中剝離子節點的哪些節點?另外,這些空標籤用於下游系統。我不是100%爲什麼他們想在xml中使用,但是我猜測它是用於其他處理的(可能是驗證;我的服務並不是必需的,因爲它位於2個隊列之間,它的唯一工作是將xml轉換爲其他系統取決於連接到Exchange對象的標頭 – jbailie1991