如何从 xpath 列表创建合并的 xml 节点(或者如何合并单个不一致的节点)
How to create a merged xml node from either a list of xpaths (OR how to merge individual inconsistent nodes)
如何从不一致的 xpath 列表创建折叠的 xml 结构?
xslt 3.0 / 2.0 是首选。
输入xml
<root>
<accepted>
<x xp="vehicle/car/models/model/part/partnumber"/>
<x xp="vehicle/car/models/model/part/vendor"/>
<x xp="vehicle/car/models/model/part/vendor/name"/>
<x xp="vehicle/car/models/model/part/vendor/email"/>
</accepted>
<rejected>
<x xp="vehicle/car/models/model/part/partnumber"/>
<x xp="vehicle/car/models/model/part/vendor"/>
<x xp="vehicle/car/models/model/part/vendor/name"/>
<x xp="vehicle/car/models/model/part/vendor/email"/>
<x xp="vehicle/car/models/model/part/vendor/telephone"/>
</rejected>
<offices>
<x xp="country/city/name"/>
<x xp="country/city/district/name"/>
<x xp="country/city/district/numberofstores"/>
<x xp="country/city/district/totalrevenue"/>
</offices>
</root>
期望输出:
<xml>
<vehicle>
<car>
<models>
<model>
<part>
<partnumber/>
<vendor>
<name/>
<email/>
<telephone/>
</vendor>
</part>
</model>
</models>
</car>
</vehicle>
<country>
<city>
<district>
<name/>
<numberofstores/>
<totalrevenue/>
</district>
</city>
</country>
</xml>
我试过的:
我使用 distinct-values() 删除了重复的 xpath,然后遍历了这个唯一字符串列表。对于每个唯一的字符串,我应用了 tokenize() 并为字符串的每个分隔部分创建了一个嵌套的 xml 元素。结果是一个 xml 节点,我将其存储在一个变量中。但现在的问题是,我最终得到了每个唯一 xpath 的子节点,我无法弄清楚如何合并这些节点。
另一个问题是如何将下面的 xml 结构合并到折叠树中? (请记住,此来源 xml 来自一个变量)
<xml>
<vehicle>
<car>
<models>
<model>
<part>
<partnumber/>
</part>
</model>
</models>
</car>
</vehicle>
<vehicle>
<car>
<models>
<model>
<part>
<vendor>
<name/>
</vendor>
</part>
</model>
</models>
</car>
</vehicle>
...
<country>
<city>
<district>
<name/>
<numberofstores/>
<totalrevenue/>
</district>
</city>
</country>
</xml>
您可以使用递归分组函数:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="#all"
version="3.0">
<xsl:function name="mf:group" as="element()*">
<xsl:param name="paths" as="xs:string*"/>
<xsl:for-each-group select="$paths" group-by="if (contains(., '/')) then substring-before(., '/') else if (. != '') then . else ()">
<xsl:element name="{current-grouping-key()}">
<xsl:sequence select="mf:group(current-group() ! substring-after(., '/'))"/>
</xsl:element>
</xsl:for-each-group>
</xsl:function>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xml>
<xsl:sequence select="mf:group(//@xp)"/>
</xml>
</xsl:template>
</xsl:stylesheet>
如何从不一致的 xpath 列表创建折叠的 xml 结构? xslt 3.0 / 2.0 是首选。
输入xml
<root>
<accepted>
<x xp="vehicle/car/models/model/part/partnumber"/>
<x xp="vehicle/car/models/model/part/vendor"/>
<x xp="vehicle/car/models/model/part/vendor/name"/>
<x xp="vehicle/car/models/model/part/vendor/email"/>
</accepted>
<rejected>
<x xp="vehicle/car/models/model/part/partnumber"/>
<x xp="vehicle/car/models/model/part/vendor"/>
<x xp="vehicle/car/models/model/part/vendor/name"/>
<x xp="vehicle/car/models/model/part/vendor/email"/>
<x xp="vehicle/car/models/model/part/vendor/telephone"/>
</rejected>
<offices>
<x xp="country/city/name"/>
<x xp="country/city/district/name"/>
<x xp="country/city/district/numberofstores"/>
<x xp="country/city/district/totalrevenue"/>
</offices>
</root>
期望输出:
<xml>
<vehicle>
<car>
<models>
<model>
<part>
<partnumber/>
<vendor>
<name/>
<email/>
<telephone/>
</vendor>
</part>
</model>
</models>
</car>
</vehicle>
<country>
<city>
<district>
<name/>
<numberofstores/>
<totalrevenue/>
</district>
</city>
</country>
</xml>
我试过的: 我使用 distinct-values() 删除了重复的 xpath,然后遍历了这个唯一字符串列表。对于每个唯一的字符串,我应用了 tokenize() 并为字符串的每个分隔部分创建了一个嵌套的 xml 元素。结果是一个 xml 节点,我将其存储在一个变量中。但现在的问题是,我最终得到了每个唯一 xpath 的子节点,我无法弄清楚如何合并这些节点。 另一个问题是如何将下面的 xml 结构合并到折叠树中? (请记住,此来源 xml 来自一个变量)
<xml>
<vehicle>
<car>
<models>
<model>
<part>
<partnumber/>
</part>
</model>
</models>
</car>
</vehicle>
<vehicle>
<car>
<models>
<model>
<part>
<vendor>
<name/>
</vendor>
</part>
</model>
</models>
</car>
</vehicle>
...
<country>
<city>
<district>
<name/>
<numberofstores/>
<totalrevenue/>
</district>
</city>
</country>
</xml>
您可以使用递归分组函数:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="#all"
version="3.0">
<xsl:function name="mf:group" as="element()*">
<xsl:param name="paths" as="xs:string*"/>
<xsl:for-each-group select="$paths" group-by="if (contains(., '/')) then substring-before(., '/') else if (. != '') then . else ()">
<xsl:element name="{current-grouping-key()}">
<xsl:sequence select="mf:group(current-group() ! substring-after(., '/'))"/>
</xsl:element>
</xsl:for-each-group>
</xsl:function>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xml>
<xsl:sequence select="mf:group(//@xp)"/>
</xml>
</xsl:template>
</xsl:stylesheet>