这个问题与我之前的问题有关XSLT 1.0: using EXSLT to get element name according to substring 我有以下XML:
<?xml version="1.0" encoding="UTF-8"?>
<GenericRecs>
<GenericRecord>
<record>
<MBH1/>
</record>
<record>
<BAL1/>
</record>
<record>
<MBH2/>
</record>
<record>
<BAL2/>
</record>
<record>
<PAY2/>
</record>
<record>
<MBH3/>
</record>
<record>
<BAL3/>
</record>
<record>
<PAY3/>
</record>
</GenericRecord>
</GenericRecs>
我想得到这个输出:
<?xml version="1.0" encoding="UTF-8"?>
<list>
<Card>
<Data>MBH1</Data>
<Data>BAL1</Data>
</Card>
<Card>
<Data>MBH2</Data>
<Data>BAL2</Data>
<Data>PAY2</Data>
</Card>
<Card>
<Data>MBH3</Data>
<Data>BAL3</Data>
<Data>PAY3</Data>
</Card>
</list>
在Tomalak的帮助下,我们提出了以下XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<list>
<xsl:apply-templates select="//record/*[starts-with(name(), 'MBH')]"/>
</list>
</xsl:template>
<xsl:template match="//record/*[starts-with(name(), 'MBH')]">
<Card>
<xsl:copy/>
</Card>
</xsl:template>
</xsl:stylesheet>
但这只给了我这个输出:
<?xml version="1.0" encoding="UTF-8"?>
<list>
<Card>
<MBH1/>
</Card>
<Card>
<MBH2/>
</Card>
<Card>
<MBH3/>
</Card>
</list>
很容易唯一地标识<MBH>
元素并列出它们。
我曾尝试使用匹配//record/*[not(starts-with(name(), 'MBH'))]
的密钥,但当然会选择与之前的<MBH>
无关的所有其他记录。
是否有可能获得具有该结构的所需输出?
XSL如何知道下一个<MBH>
元素的(变化的)元素数量?
感谢您对此提供任何帮助。
祝你好运, 彼得
答案 0 :(得分:2)
此XSLT 1.0转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kByNameSuf" match="record/*"
use="translate(name(), translate(name(),'0123456789',''),'')"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"record[generate-id(*[1])
=
generate-id(key('kByNameSuf',
translate(name(*[1]),
translate(name(*[1]),'0123456789',''),'')
)[1]
)
]
">
<Card>
<xsl:for-each select=
"key('kByNameSuf',
translate(name(*[1]),
translate(name(*[1]),'0123456789',''),'')
)
">
<Data><xsl:value-of select="name()"/></Data>
</xsl:for-each>
</Card>
</xsl:template>
<xsl:template match="record"/>
</xsl:stylesheet>
应用于提供的XML文档时:
<GenericRecs>
<GenericRecord>
<record>
<MBH1/>
</record>
<record>
<BAL1/>
</record>
<record>
<MBH2/>
</record>
<record>
<BAL2/>
</record>
<record>
<PAY2/>
</record>
<record>
<MBH3/>
</record>
<record>
<BAL3/>
</record>
<record>
<PAY3/>
</record>
</GenericRecord>
</GenericRecs>
生成想要的正确结果:
<GenericRecs>
<GenericRecord>
<Card>
<Data>MBH1</Data>
<Data>BAL1</Data>
</Card>
<Card>
<Data>MBH2</Data>
<Data>BAL2</Data>
<Data>PAY2</Data>
</Card>
<Card>
<Data>MBH3</Data>
<Data>BAL3</Data>
<Data>PAY3</Data>
</Card>
</GenericRecord>
</GenericRecs>
<强>解释强>:
使用Muenchian Grouping。
假设只有名字后缀的数字。
使用双翻译方法(由Michael Kay首先提出)。
<强> II。 XSLT 2.0解决方案:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="GenericRecord">
<xsl:for-each-group select="*"
group-by="replace(name(*[1]), '^.*(\d+)$', '$1')">
<Card>
<xsl:for-each select="current-group()">
<Data><xsl:value-of select="name(*[1])"/></Data>
</xsl:for-each>
</Card>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>