我有一个示例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>这实际上意味着文档结构保持不变,但是一些“选择的”元素被重命名。这些选定的元素以相同的前缀开头(在本例中以“子类型-”开头),但有不同的后缀("A“、"B”、“x”、"C“等)。
为什么这么麻烦?我有一个软件需要一个xml文件作为输入。为了方便起见,我使用XML模式轻松地编辑xml文件,该模式有助于确保xml文件是正确的。遗憾的是,当涉及到上下文敏感的方面时,XML模式有点缺乏。这将导致xml文件如/before转换/所示。该软件无法处理这样的xml文件,因为它需要一个文件,如/after转换/中所示。因此,需要进行转型。
我想用XSLT进行转换,并且我已经知道了如何这样做。我的方法是为身份转换定义一个规则,为每个需要重命名的“子类型-*”元素定义一个规则。这个解决方案可以工作,但它没有那么优雅。你最终会有很多规矩。
--- 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>
...有办法把它浓缩成两条规则吗?一个用于身份转换,另一个用于所有“子类型-*”元素?也许可以结合使用XSLT和一些正则表达式?还是你必须采取不同的方法来解决这个问题?
发布于 2011-05-20 07:44:27
(修订了我的答覆)
这段代码片段可以很好地处理示例XML。我合并了这两个模板,因为它们都希望对“所有元素”进行操作。我以前的模板没有工作,因为两者匹配相同的选择。
<xsl:template match="@*|node()">
<xsl:choose>
<xsl:when test="starts-with(name(), 'child-type')">
<xsl:element name="child-node">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>给定您的源XML:
<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>这将产生以下结果:
<root-node>
<child-node> ... </child-node>
<child-node> ... </child-node>
<child-node> ... </child-node>
<child-node>
<child-node> ... </child-node>
</child-node>
</root-node>发布于 2011-05-20 07:35:43
XSLtT有一个一开始-函数,它可以用来识别以'child-type'开头的元素,允许您使用单个模板匹配。见以下相关问题:
发布于 2011-05-20 14:06:11
通过将意义附加到元素名称的内部语法(在极端情况下,可以有一个以根元素<Surname_Kay.Firstname_Michael.Country_UK/>的名称捕获所有信息的XML文档)来捕获信息不是一个好主意。但是,如果您有这种形式的数据,当然可以处理它,例如使用表单<xsl:template match="*[matches(name(), 'child-type-[A-Z]')]">的模板规则
https://stackoverflow.com/questions/6068764
复制相似问题