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>
答
另一种方式,你可以看看:
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>
我没有看到你需要的身份转换模板。 –
Blimmey!帽子掉了。谢谢。 无论如何,默认优先级是什么?这是否意味着最高优先级将被首先执行,然后跳过具有相同模式的其他模板?优先级如何工作 – Barjack
@Barjack,请参阅https://www.w3.org/TR/xslt#conflict了解优先级规则,它取决于模板类型,如果模板没有'priority'属性。 –