我有一个大型XML文件,其结构如下:
<text n="1">
<front>
<title n="t1-1">A</title>
<title n="t1-2">B</title>
</front>
<body>
<p>
<seg n="1-1">some <add>foo</add> text</seg>
<seg n="1-2">some <add>foo</add> <add>foo</add> text</seg>
<seg n="1-3">some <add>foo</add> text</seg>
</p>
</body>
</text>
<text n="2">
<front>
<title n="t2-1">X</title>
<title n="t2-2">Y</title>
</front>
<body>
<p>
<seg n="2-1">some <add>foo</add> text</seg>
<seg n="2-2">some <add>foo</add> text</seg>
<seg n="2-3">some text</seg>
</p>
</body>
</text>
<text>
.....
</text>
我想将其转换为一个新的XML文档,结构如下:
<document>
<p n="1">
<newtitle>A B</title>
<seg n="1-1">some text</seg>
<seg n="1-2">some text</seg>
<seg n="1-3">some text</seg>
<adds>
<add>foo</add>
<add>foo</add>
<add>foo</add>
<add>foo</add>
</adds>
</p>
<p n="2">
<newtitle>X Y</title>
<seg n="2-1">some text</seg>
<seg n="2-2">some text</seg>
<seg n="2-3">some text</seg>
<adds>
<add>foo</add>
<add>foo</add>
</adds>
</p>
<p>
....
</p>
</document>
我已尝试使用identity transform与xsl:for-each
进行多次尝试,但无法正确提取和重新排列。
提前感谢您的任何帮助。
答案 0 :(得分:1)
这是一个XSLT 3解决方案(对于XSLT 2,您需要使用身份转换模板拼出<xsl:mode on-no-match="shallow-copy"/>
):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="root">
<document>
<xsl:apply-templates/>
</document>
</xsl:template>
<xsl:template match="text">
<p>
<xsl:apply-templates select="@* | node()"/>
</p>
</xsl:template>
<xsl:template match="text/front">
<newtitle>
<xsl:value-of select="title"/>
</newtitle>
</xsl:template>
<xsl:template match="text/body">
<xsl:apply-templates select="p/seg"/>
<adds>
<xsl:apply-templates select="p/seg/add"/>
</adds>
</xsl:template>
<xsl:template match="text/body/p/seg">
<xsl:copy>
<xsl:apply-templates select="@* | text()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
正如您所看到的,通过将任务分解为模板以将每个节点转换为其目标,您将获得结构良好的方法。
上的在线示例