[英]Convert flat XML data into nested XML using XSLT1.0
I have a grouping issue where i need to group all the keys that has the same number under a node.我有一个分组问题,我需要将节点下具有相同编号的所有键分组。 For eg, my XML looks like :
例如,我的 XML 看起来像:
<results>
<status>completed</status>
<info>success</info>
<prod1>abc</prod1>
<pub1>test</pub1>
<sub1>123</sub1>
<subtype1>pt</subtype1>
<prod2>def</prod2>
<pub2>test22</pub2>
<sub2>456</sub2>
<subtype2>pt</subtype2>
<prod3>ghi</prod3>
<pub3>test33</pub3>
<sub3>789</sub3>
<subtype3>pt</subtype3>
</results>
I need to convert the above into:我需要将上述内容转换为:
<results>
<status>completed</status>
<info>success</info>
<products>
<product>
<prod>abc</prod>
<pub>test</pub>
<sub>123</sub>
<subtype>pt</subtype>
</product>
<product>
<prod>def</prod>
<pub>test22</pub>
<sub>456</sub>
<subtype>pt</subtype>
</product>
<product>
<prod>ghi</prod>
<pub>test33</pub>
<sub>789</sub>
<subtype>pt</subtype>
</product>
</products>
</results>
Any help in resolving the above is highly appreciated.对解决上述问题的任何帮助表示高度赞赏。 I am currently stuck with this issue and not able to proceed.
我目前被这个问题困住了,无法继续。
The below xslt pulls each element and puts into a node and im not able to group all elements that ends with a particular number into a single node.下面的 xslt 拉出每个元素并放入一个节点中,我无法将所有以特定数字结尾的元素分组到一个节点中。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="elementByRow" match="/*/*"
use="(name(.)[1])" />
<xsl:template match="/messages">
<messages>
<!-- pick out the first RowN.* element for each N -->
<xsl:apply-templates select="*[generate-id() =
generate-id(key('elementByRow', name(.))[1])]" />
</messages>
</xsl:template>
<xsl:template match="*">
<row>
<!-- process _all_ the elements that belong to this row -->
<xsl:for-each select="key('elementByRow', name(.))[1]">
<xsl:element name="{name(.)[1]}">
<xsl:value-of select="." />
</xsl:element>
</xsl:for-each>
</row>
</xsl:template>
</xsl:stylesheet>
If the input structure is constant, I would take advantage of that, instead of trying to group by the trailing number.如果输入结构是恒定的,我会利用它,而不是尝试按尾随数字分组。
For example, you could do:例如,你可以这样做:
XSLT 1.0 XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/results">
<xsl:copy>
<xsl:copy-of select="status | info"/>
<products>
<xsl:for-each select="*[starts-with(name(), 'prod')]">
<product>
<prod>
<xsl:value-of select="." />
</prod>
<pub>
<xsl:value-of select="following-sibling::*[1]" />
</pub>
<sub>
<xsl:value-of select="following-sibling::*[2]" />
</sub>
<subtype>
<xsl:value-of select="following-sibling::*[3]" />
</subtype>
</product>
</xsl:for-each>
</products>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Here's a more elaborate approach that groups the elements by their number;这是一种更精细的方法,它按元素的数量对元素进行分组; note, however, that this assumes an element's name will not contain any digits other than the group number at the end.
但是请注意,这假定元素的名称将不包含末尾组编号以外的任何数字。
XSLT 1.0 XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="field-by-group" match="*" use="translate(name(), translate(name(), '0123456789', ''), '')" />
<xsl:template match="/results">
<xsl:copy>
<xsl:copy-of select="status | info"/>
<products>
<xsl:for-each select="*[starts-with(name(), 'prod')]">
<product>
<xsl:for-each select="key('field-by-group', substring-after(name(), 'prod'))">
<xsl:element name="{translate(name(), '0123456789', '')}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</product>
</xsl:for-each>
</products>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.