2010-06-06 103 views
2

寻求使用XSLT来转换我的XML。示例XML如下:使用XSLT重构XML节点

<root> 
<info> 
    <firstname>Bob</firstname> 
    <lastname>Joe</lastname> 
</info> 
<notes> 
    <note>text1</note> 
    <note>text2</note> 
</notes> 
<othernotes> 
    <note>text3</note> 
    <note>text4</note> 
</othernotes> 

我在寻找提取所有“笔记”元素,并让他们父节点下的“注意事项”。

我在寻找的结果如下:

<root> 
<info> 
    <firstname>Bob</firstname> 
    <lastname>Joe</lastname> 
</info> 
<notes> 
    <note>text1</note> 
    <note>text2</note> 
    <note>text3</note> 
    <note>text4</note> 
</notes> 
</root> 

我试图用的是让我来提取我的“笔记”的XSLT,但我想不通我怎么能将它们重新包装在“笔记”节点中。

下面是我使用的XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

    <xsl:template match="notes|othernotes"> 
     <xsl:apply-templates select="note"/> 
    </xsl:template> 
    <xsl:template match="*"> 
    <xsl:copy><xsl:apply-templates/></xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

我与上面的XSLT得到的结果是:

<root> 
<info> 
    <firstname>Bob</firstname> 
    <lastname>Joe</lastname> 
</info> 
    <note>text1</note> 
    <note>text2</note> 
    <note>text3</note> 
    <note>text4</note> 
</root> 

感谢

回答

2

可以产生这样的内容:

<xsl:element name="notes"> 
    <!-- inject content of notes element here using e.g. <xsl:copy> or <xsl:copy-of> --> 
</xsl:element> 

稍做修改上述方法也适用于在特定XML名称空间中生成元素。 但是因为你是不是想找来生成命名空间的元素存在一个快捷方式:

<notes> 
    <!-- inject content of notes element here using e.g. <xsl:copy> or <xsl:copy-of> --> 
</notes> 

在你的具体的例子,我会调整你的样式表来执行以下操作:

<xsl:template match="root"> 
    <root> 
    <xsl:copy-of select="info"/> 
    <notes> 
     <xsl:copy-of select="*/note"/> 
    </notes> 
    </root> 
</xsl:template> 
+1

不错,干净,+1。我想用来代替重新创建,这是我个人偏好的问题。另外,要创建特定命名空间中的元素,您可以轻松声明一个前缀并使用它:''。 ''实际上只在元素名称应该是动态时才需要。 – Tomalak 2010-06-06 21:08:36

1

你会寻找对于这样的事情: -

<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="/root"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()[local-name() != 'notes' and local-name() != 'othernotes'] 
    </xsl:copy> 
    <notes> 
    <xsl:apply-templates select="othernotes/note | notes/note" /> 
    </notes> 
</xsl:template> 

您可以控制根节点的结构。首先复制未命名为“笔记”或“其他注释”的根目录下的所有内容。然后直接创建一个“notes”元素,然后合并所有在“othernotes”或“notes”元素下面的“note”元素。

+0

'select =“@ * | node()[not(self :: notes or self :: othernotes)]”';-)(尽管在这个例子中'select =“info”'会产生同样的效果...... ) – Tomalak 2010-06-06 21:01:46

+0

@Tomalak:其实我确实有这个,但是把它改回到使用本地名称,我想不出现在为什么。 @ user268396的 解决方案在一个非常具体的例子中起作用,我正在做最小的假设(其他兄弟可能会出现信息,信息可能包含一个不受此合并影响的音符元素等) – AnthonyWJones 2010-06-07 09:31:22

+0

这就是为什么我给+1解。我有一个类似的准备,但你更快,所以我没有发布它。 :) – Tomalak 2010-06-07 10:15:15