基于 XPATH 创建 XML 个节点
Creating XML nodes based on XPATH
我需要使用 XPATH 添加 XML 个节点。我从 Whosebug 中的另一个线程得到了下面的 XSLT,它完成了这项工作。
但我面临一个问题,如果我们不维护 XSLT 中 XPATH 的顺序,那么它会多次创建相同的 XML 标签。请参考下面的示例 XML 和 XSLT 以更好地理解它。请帮助解决这个问题。
输入XML:
<header>
<txCtry>SG</txCtry>
<msgId>b626c6be4a724f8aa92dcba1b4e07cf0</msgId>
</header>
<data>
<txCtry>SG</txCtry>
<txCityCd>SIN</txCityCd>
</data>
XSLT:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="my:my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vPop" as="element()*">
<item path="/header/txCtryyyy">F</item>
<item path="/header/btchBookg">ddddddddddddd</item>
<item path="/data/txSttlmInf/instgRmbrsmntAgt/BICFIIIIII">FXZ9200136548878</item>
<item path="/header/prcgSubSts">ooooooooooooooo</item>
</xsl:variable>
<xsl:template match="/">
<xsl:sequence select="my:subTree($vPop/@path/concat(.,'/',string(..)))"/>
</xsl:template>
<xsl:function name="my:subTree" as="node()*">
<xsl:param name="pPaths" as="xs:string*"/>
<xsl:for-each-group select="$pPaths"
group-adjacent=
"substring-before(substring-after(concat(., '/'), '/'), '/')">
<xsl:if test="current-grouping-key()">
<xsl:choose>
<xsl:when test=
"substring-after(current-group()[1], current-grouping-key())">
<xsl:element name=
"{substring-before(concat(current-grouping-key(), '['), '[')}">
<xsl:sequence select=
"my:subTree(for $s in current-group()
return
concat('/',substring-after(substring($s, 2),'/'))
)
"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="current-grouping-key()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:for-each-group>
</xsl:function>
</xsl:stylesheet>
已转换 XML:
<header>
<txCtryyyy>F</txCtryyyy>
</header>
<data>
<txSttlmInf>
<instgRmbrsmntAgt>
<BICFIIIIII>FXZ9200136548878</BICFIIIIII>
</instgRmbrsmntAgt>
</txSttlmInf>
</data>
<header>
<btchBookg>ddddddddddddd</btchBookg>
</header>
<data>
<txSttlmInf>
<instgRmbrsmntAgt>
<BICFHHHH>FXZ92001365kkkkkkkk48878</BICFHHHH>
</instgRmbrsmntAgt>
</txSttlmInf>
</data>
<header>
<prcgSubSts>ooooooooooooooo</prcgSubSts>
</header>
在这里我们可以看到 header 和数据标签被多次创建。
预期输出:
<header>
<txCtryyyy>F</txCtryyyy>
<btchBookg>ddddddddddddd</btchBookg>
<prcgSubSts>ooooooooooooooo</prcgSubSts>
</header>
<data>
<txSttlmInf>
<instgRmbrsmntAgt>
<BICFIIIIII>FXZ9200136548878</BICFIIIIII>
<BICFHHHH>FXZ92001365kkkkkkkk48878</BICFHHHH>
</instgRmbrsmntAgt>
</txSttlmInf>
</data>
尝试在你有 <xsl:for-each-group select="$pPaths" group-adjacent="substring-before(substring-after(concat(., '/'), '/'), '/')">
的函数中使用 group-by
而不是 group-adjacent
,尝试使用 <xsl:for-each-group select="$pPaths" group-by="substring-before(substring-after(concat(., '/'), '/'), '/')">
.
我需要使用 XPATH 添加 XML 个节点。我从 Whosebug 中的另一个线程得到了下面的 XSLT,它完成了这项工作。 但我面临一个问题,如果我们不维护 XSLT 中 XPATH 的顺序,那么它会多次创建相同的 XML 标签。请参考下面的示例 XML 和 XSLT 以更好地理解它。请帮助解决这个问题。
输入XML:
<header>
<txCtry>SG</txCtry>
<msgId>b626c6be4a724f8aa92dcba1b4e07cf0</msgId>
</header>
<data>
<txCtry>SG</txCtry>
<txCityCd>SIN</txCityCd>
</data>
XSLT:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="my:my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vPop" as="element()*">
<item path="/header/txCtryyyy">F</item>
<item path="/header/btchBookg">ddddddddddddd</item>
<item path="/data/txSttlmInf/instgRmbrsmntAgt/BICFIIIIII">FXZ9200136548878</item>
<item path="/header/prcgSubSts">ooooooooooooooo</item>
</xsl:variable>
<xsl:template match="/">
<xsl:sequence select="my:subTree($vPop/@path/concat(.,'/',string(..)))"/>
</xsl:template>
<xsl:function name="my:subTree" as="node()*">
<xsl:param name="pPaths" as="xs:string*"/>
<xsl:for-each-group select="$pPaths"
group-adjacent=
"substring-before(substring-after(concat(., '/'), '/'), '/')">
<xsl:if test="current-grouping-key()">
<xsl:choose>
<xsl:when test=
"substring-after(current-group()[1], current-grouping-key())">
<xsl:element name=
"{substring-before(concat(current-grouping-key(), '['), '[')}">
<xsl:sequence select=
"my:subTree(for $s in current-group()
return
concat('/',substring-after(substring($s, 2),'/'))
)
"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="current-grouping-key()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:for-each-group>
</xsl:function>
</xsl:stylesheet>
已转换 XML:
<header>
<txCtryyyy>F</txCtryyyy>
</header>
<data>
<txSttlmInf>
<instgRmbrsmntAgt>
<BICFIIIIII>FXZ9200136548878</BICFIIIIII>
</instgRmbrsmntAgt>
</txSttlmInf>
</data>
<header>
<btchBookg>ddddddddddddd</btchBookg>
</header>
<data>
<txSttlmInf>
<instgRmbrsmntAgt>
<BICFHHHH>FXZ92001365kkkkkkkk48878</BICFHHHH>
</instgRmbrsmntAgt>
</txSttlmInf>
</data>
<header>
<prcgSubSts>ooooooooooooooo</prcgSubSts>
</header>
在这里我们可以看到 header 和数据标签被多次创建。
预期输出:
<header>
<txCtryyyy>F</txCtryyyy>
<btchBookg>ddddddddddddd</btchBookg>
<prcgSubSts>ooooooooooooooo</prcgSubSts>
</header>
<data>
<txSttlmInf>
<instgRmbrsmntAgt>
<BICFIIIIII>FXZ9200136548878</BICFIIIIII>
<BICFHHHH>FXZ92001365kkkkkkkk48878</BICFHHHH>
</instgRmbrsmntAgt>
</txSttlmInf>
</data>
尝试在你有 <xsl:for-each-group select="$pPaths" group-adjacent="substring-before(substring-after(concat(., '/'), '/'), '/')">
的函数中使用 group-by
而不是 group-adjacent
,尝试使用 <xsl:for-each-group select="$pPaths" group-by="substring-before(substring-after(concat(., '/'), '/'), '/')">
.