xPath XSLT Get Parent Element 及其子元素和孙元素



我需要帮助来更改这样的 xml 结构

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

正如您在第二个模板标签中看到的那样,在我尝试手动列出每个元素标签之前,但它很耗时。所以现在我想检查父元素,递归地更改所有子元素,并分别添加前缀。你可以看到我在第三个模板标签中尝试过。但它失败了。 那我该怎么做呢?另外需要注意的是,我们可以覆盖某些字段以不遵守上述规则。例如,根节点 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>

谢谢

编辑: 还有另一个信息。所有子节点递归地属于应该具有前缀核心的父节点,其前缀中不可能有typ。虽然父元素的每个子节点都有 typ 前缀,但它的子节点有可能具有核心前缀。所以也许我们可以默认为根元素的子元素添加前缀typ,然后我们可以指定哪些孩子应该有核心前缀

您可以为其他元素编写模板,并确保设置优先级:

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

另一种看待它的方式:

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>

最新更新