0

我有一些不友好且半生不熟的 xml 文件,类似于以下内容:

<root>
<child0><name0>Bob Dylan</name0></child0>
<child1><name1>Daft Punk</name1></child1>
<child2><name2>Nine Inch Nails</name2></child2>
</root>

我希望将每个文件转换为以下内容:

<root><children>
<child><name>Bob Dylan</name></child>
<child><name>Daft Punk</name></child>
<child><name>Nine Inch Nails</name></child> 
</children>
</root>

每个文件都没有确定的子文件数量。有些人只有<child0>而有些人有<child0> ... <child10>。儿童中的元素也没有确定,例如。名称[0]等

所以我想遍历每个孩子(可能使用通配符或结尾,或??)以匹配始终终止孩子和孩子的孩子元素的数字。

这不起作用,但类似于:

<xsl:for-each select="child*" >
     <child>
     <name><xsl:value-of select="name[index]"></name>
     </child>
</xsl:for-each>

我看到了很多选择、if 和 match 条件的例子,这些条件处理选择元素内的内容(或通过位置或索引的方式选择元素)......因为这就是它应该完成的方式。

但我有有效但半生不熟的 xml。

4

2 回答 2

2

这是一个简单的、面向推送的解决方案,可以实现您想要的。请注意,它可以使用 XSLT/XPath 1.0 或 2.0 工作。

当这个 XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output omit-xml-declaration="yes" indent="yes" />
  <xsl:strip-space elements="*" />

  <xsl:template match="/*">
    <root>
      <children>
        <xsl:apply-templates />
      </children>
    </root>
  </xsl:template>

  <xsl:template match="*[starts-with(name(), 'child')]">
    <child>
      <xsl:apply-templates />
    </child>
  </xsl:template>

  <xsl:template match="*[starts-with(name(), 'name')]">
     <name>
       <xsl:apply-templates />
     </name>
  </xsl:template>

</xsl:stylesheet>

...应用于原始 XML:

<root>
  <child0>
    <name0>Bob Dylan</name0>
  </child0>
  <child1>
    <name1>Daft Punk</name1>
  </child1>
  <child2>
    <name2>Nine Inch Nails</name2>
  </child2>
</root>

...产生了想要的结果:

<root>
  <children>
    <child>
      <name>Bob Dylan</name>
    </child>
    <child>
      <name>Daft Punk</name>
    </child>
    <child>
      <name>Nine Inch Nails</name>
    </child>
  </children>
</root>
于 2012-12-01T22:56:05.440 回答
0

一种简单的方法是在 name() 值上使用正则表达式:

<xsl:for-each select="*[matches(name(),'^child\d$')]">
...
于 2012-12-01T21:35:35.843 回答