用于带有任意标记的XML文档的XSLT

用于带有任意标记的XML文档的XSLT,xml,xslt,xpath,Xml,Xslt,Xpath,为了澄清标题,我有一个如下所示的XML文档: <group> <starter>Start</starter> <backup1>Backup1</backup1> </group> <group> <starter>Another starter</starter> <backup1>Backup1</backup1> <backup2&

为了澄清标题,我有一个如下所示的XML文档:

<group>
  <starter>Start</starter>
  <backup1>Backup1</backup1>
</group>
<group>
  <starter>Another starter</starter>
  <backup1>Backup1</backup1>
  <backup2>Backup2</backup2>
  <backup3>Backup3</backup3>
  <reserve>Reserve</reserve>
</group>
<xsl:for-each select="group/backup">

开始
备份1
另一个发令者
备份1
备份2
备份3
储备
因此,每个组可以有任意数量的
标记。我需要确保我的XSLT获取了所有这些文件,并将它们重命名为“backup\n”。通常,我的XSLT将应用符合以下要求的内容:

<group>
  <starter>Start</starter>
  <backup1>Backup1</backup1>
</group>
<group>
  <starter>Another starter</starter>
  <backup1>Backup1</backup1>
  <backup2>Backup2</backup2>
  <backup3>Backup3</backup3>
  <reserve>Reserve</reserve>
</group>
<xsl:for-each select="group/backup">

并围绕xpath选择进行循环。这显然不会起作用,因为即使只有一个备份,它仍然被命名为
,并且可以有任意数量的
标记


像这样循环任意标记的最佳方法是什么?我使用的是XSLT1.0,所以不能真正使用XSLT2.0

如果需要名称以
backup
开头的所有元素,可以使用

<xsl:for-each select="group/*[starts-with(local-name(), 'backup')]">

(这看起来很奇怪,但诀窍是如果
子字符串(local-name(),7)
不是一个有效的数字,那么测试将变成
NaN=NaN
,这总是错误的-
NaN
不等于任何东西,甚至不等于它本身)。

,是否还要获取索引,以便我可以从
backup1
backup2
中检索
1
2
中的随机位为每个
获取元素的
本地名称的
子字符串,或者使用
位置()
函数获取当前节点在所选列表中的位置。这可能与元素名称的尾随部分不同,例如,如果组中有两个名为
backup2
backup5
的备份元素,则
position()
仍将为您提供1和2,而子字符串将为您提供2和5。感谢您提供了精彩而详细的答案。如果允许,我会尽快将其标记为正确的。您有一个元素名称不正确的文档(
),并且希望将其转换为另一个元素名称不正确的文档(
)?如果您有电源,请将其更改为
,正是出于这些原因,你才提出了这个问题。相等的元素应该有相等的名称,因为如果没有,事情就会变得糟糕。我很想这样做——不幸的是,我无法控制XML的源代码。我正在将它转换为JSON,我只需要一种获取索引的方法,这样我就可以使JSON更合理。啊,我明白了。我甚至不想让您更改源代码,我只是想阻止您创建同样破碎的目标XML。但既然您转换为JSON,那就没关系了。:)您可以使用
position()
来获取索引,而不必使用
substring-after()
查看名称“后缀”。当然,你可以,但这很麻烦。如果我将其转换为JSON,我会使用一个数组进行备份,类似于
{“starter”:“另一个starter”,“backups”:[“Backup1”,“Backup2”,“Backup3”],“reserves”:[“Reserve”]}