2017-08-24 128 views
1

我需要幫助的XML結構這樣XPATH XSLT獲取父元素及其子子孫孫

<AcctInqRq> 
<MsgRqHdr> 
    <RqUID>86eb9644-decf-4fa2-bd16-6d5403a8660a</RqUID> 
    <ChannelId>897</ChannelId> 
</MsgRqHdr> 
<InqInfo> 
    <FromAccount> 
     <AccountId>11012442</AccountId> 
     <AccountCurrency/> 
    </FromAccount> 
</InqInfo> 
<RefInfo> 
    <RefName>AppCallerName</RefName> 
    <RefValue>API_GATEWAY</RefValue> 
</RefInfo> 
</AcctInqRq> 

改變這種

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="http://www.some.com/esb/inquiry/acct/types" xmlns:core="http://www.some.com/esb/shared/core"> 
    <soapenv:Header/> 
    <soapenv:Body> 
     <typ:AcctInqRq> 
     <core:MsgRqHdr> 
      <core:RqUID>86eb9644-decf-4fa2-bd16-6d5403a8660a</core:RqUID> 
      <core:ChannelId>897</core:ChannelId> 
     </core:MsgRqHdr> 
     <typ:InqInfo> 
      <typ:FromAccount> 
       <typ:AccountId>11012442</typ:AccountId> 
       <typ:AccountCurrency/> 
      </typ:FromAccount> 
     </typ:InqInfo> 
     <core:RefInfo> 
      <core:RefName>AppCallerName</core:RefName> 
      <core:RefValue>API_GATEWAY</core:RefValue> 
     </core:RefInfo> 
     </typ:AcctInqRq> 
    </soapenv:Body> 
</soapenv:Envelope> 

這是我目前的XSLT

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:typ="http://www.some.com/esb/inquiry/acct/types" 
xmlns:core="http://www.some.com/esb/shared/core" 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" encoding="utf-8"/> 
    <xsl:template match="/"> 
     <soapenv:Envelope> 
      <soapenv:Header/> 
      <soapenv:Body> 
       <xsl:apply-templates/> 
      </soapenv:Body> 
     </soapenv:Envelope> 
    </xsl:template> 
    <xsl:template match="AcctInqRq|InqInfo|FromAccount|AccountId|AccountCurrency|ToAccount|AccountId|AccountCurrency|ChequeNo|RetrievalNo|SlipNo"> 
     <xsl:element name="typ:{local-name()}"> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:element> 
    </xsl:template> 
    <xsl:template match="MsgRqHdr"> 
     <xsl:for-each select="*"> 
      <xsl:element name="core:{local-name()}"> 
       <xsl:apply-templates select="@*|node()"/> 
      </xsl:element> 
     </xsl:for-each> 
    </xsl:template> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

正如您在第二個模板標籤中可以看到的,然後我嘗試手動列出每個元素標籤,但是它的t消耗時間。所以現在我想檢查父元素,並遞歸地更改所有的子元素,並分別添加前綴。你可以看到我在第三個模板標籤中嘗試過。但它失敗了。 那麼我該怎麼做?另一個說明,我們可以覆蓋一些領域,不遵守上述規則。例如,AccInqRq的根節點應該添加前綴typ,但是它的後代(如MsgRqHdr和RefInfo)應該添加前綴核心。

所以我大概是覺得這樣的事情(CMIIW)

..upper xsl code.. 
<xsl:template match="MsgRqHdr | RefInfo | *other parent element to be added prefix core* 
</xsl:template> 

<xsl:template match="InqInfo| *other parent element to be added prefix typ* 
</xsl:template> 

<xsl:template match=" *probably add this one to override some field with specific prefix typ* 
</xsl:template> 

感謝

編輯: 還有另一種信息。所有子節點遞歸地應該具有前綴核心,其不可能具有典型的前綴。雖然每個具有典型前綴的父元素的子節點,但其子節點可能有核心前綴。因此,也許我們可以在默認情況下使其前綴典型值添加到根元素的孩子,再經過我們可以指定哪些孩子應該有核心前綴

回答

2

你可以寫那些其他元素的模板,並確保您設置優先級:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:typ="http://www.some.com/esb/inquiry/acct/types" 
    xmlns:core="http://www.some.com/esb/shared/core" 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 

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

    <xsl:template match="/"> 
     <soapenv:Envelope> 
      <soapenv:Header/> 
      <soapenv:Body> 
       <xsl:apply-templates/> 
      </soapenv:Body> 
     </soapenv:Envelope> 
    </xsl:template> 

    <xsl:template match="AcctInqRq | AcctInqRq//*"> 
     <xsl:element name="typ:{local-name()}"> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="MsgRqHdr | MsgRqHdr//* | RefInfo | RefInfo//*" priority="5"> 
     <xsl:element name="core:{local-name()}"> 
       <xsl:apply-templates select="@*|node()"/> 
      </xsl:element> 
    </xsl:template> 

</xsl:stylesheet> 
+0

我沒有看到你需要的身份轉換模板。 –

+0

Blimmey!帽子掉了。謝謝。 無論如何,默認優先級是什麼?這是否意味着最高優先級將被首先執行,然後跳過具有相同模式的其他模板?優先級如何工作 – Barjack

+0

@Barjack,請參閱https://www.w3.org/TR/xslt#conflict瞭解優先級規則,它取決於模板類型,如果模板沒有'priority'屬性。 –

2

另一種方式,你可以看看:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:typ="http://www.some.com/esb/inquiry/acct/types" 
xmlns:core="http://www.some.com/esb/shared/core"> 
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" encoding="utf-8"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/AcctInqRq"> 
    <soapenv:Envelope> 
     <soapenv:Header/> 
     <soapenv:Body> 
      <typ:AcctInqRq> 
       <xsl:apply-templates select="MsgRqHdr" mode="core"/> 
       <xsl:apply-templates select="InqInfo" mode="typ"/> 
       <xsl:apply-templates select="RefInfo" mode="core"/> 
      </typ:AcctInqRq> 
     </soapenv:Body> 
    </soapenv:Envelope> 
</xsl:template> 

<xsl:template match="*" mode="typ"> 
    <xsl:element name="typ:{local-name()}"> 
     <xsl:apply-templates mode="typ"/> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="*" mode="core"> 
    <xsl:element name="core:{local-name()}"> 
     <xsl:apply-templates mode="core"/> 
    </xsl:element> 
</xsl:template> 

</xsl:stylesheet>