简体   繁体   中英

xPath XSLT Get Parent Element and its children and grandchildren

I need help to change the xml structure like this

<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>

to this

<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>

This is my current 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>

As you can see in the second template tag before I've tried to list every single element tag manually, but its time consuming. So now I want to check the parent element, and change all the children recursively, and add the prefix respectively. You can see I tried that in third template tag. But its failed. So how can I do that? Another note, we can override some field to not adhere above rules. For instance the root node which is AccInqRq, should be add with prefix typ, but its descendants like MsgRqHdr and RefInfo should be added prefix core.

So I presumably think something like this (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>

Thanks

EDIT: There is another information. All children node recursively of the parent which should have prefix core , its impossible for having typ in its prefix. While every children node of the parent element which have typ prefix, there is possiblity its children have core prefix. So maybe we can make it by default to add prefix typ to children of root element, and after then we can specify which children should have core prefix

You can write a template for those other elements and make sure you set the priority:

<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>

Another way you could look at it:

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM