XPATH XSLT获取父元素及其子子孙孙

问题描述:

我需要帮助的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> 

感谢

编辑: 还有另一种信息。所有子节点递归地应该具有前缀核心,其不可能具有典型的前缀。虽然每个具有典型前缀的父元素的子节点,但其子节点可能有核心前缀。因此,也许我们可以在默认情况下使其前缀典型值添加到根元素的孩子,再经过我们可以指定哪些孩子应该有核心前缀

你可以写那些其他元素的模板,并确保您设置优先级:

<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'属性。 –

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

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>