【发布时间】:2011-08-29 10:51:44
【问题描述】:
我有一个示例 xml 文件,如下所示:
--- before transformation ---
<root-node>
<child-type-A> ... </child-type-A>
<child-type-A> ... </child-type-A>
<child-type-B> ... </child-type-B>
<child-type-C>
<child-type-B> ... </child-type-B>
...
</child-type-C>
...
</root-node>
我想把这个 xml 文件转换成类似这样的东西:
--- after transformation ---
<root-node>
<child-node> ... </child-node>
<child-node> ... </child-node>
<child-node> ... </child-node>
<child-node>
<child-node> ... </child-node>
...
</child-node>
...
</root-node>
实际上这意味着文档结构保持不变,但一些“选择”的元素被重命名。这些选择的元素以相同的前缀开头(在本例中为“child-type-”),但具有不同的后缀(“A”|“B”|“C”|等)。
为什么要这么麻烦?我有一个需要 xml 文件作为输入的软件。为方便起见,我使用 XML 模式轻松编辑 xml 文件,该模式有助于确保 xml 文件正确无误。遗憾的是,XML 模式在上下文敏感性方面有些欠缺。这导致 xml 文件看起来像 /before transformation/ 中所示。该软件无法处理这样的 xml 文件,因为它需要 /after transformation/ 中所示的文件。因此需要转型。
我想用 XSLT 进行转换,并且我已经想出了如何去做。我的方法是为身份转换定义一个规则,并为每个需要重命名的“child-type-*”元素定义一个规则。这个解决方案有效,但它不是那么优雅。你最终会得到很多规则。
--- sample transformation rules ---
<!-- Identity transformation -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="child-type-A">
<xsl:element name="child-node">
<xsl:apply-templates select="@*|node()" />
</xsl:element>
</xsl:template>
...
有没有办法把它浓缩成两条规则?一个用于身份转换,一个用于所有“child-type-*”元素?也许通过将 XSLT 与一些正则表达式结合使用?还是您必须采取不同的方法来解决此类问题?
【问题讨论】:
-
好问题,+1。有关两个完整且通用的 XSLT(1.0 和 2.0)解决方案,请参阅我的答案。
标签: regex xslt xpath element renaming