XSLT XML到XML转换,同时替换和重新排列节点

时间:2017-12-23 13:55:56

标签: xml xslt

我有一个大型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 transformxsl:for-each进行多次尝试,但无法正确提取和重新排列。

提前感谢您的任何帮助。

1 个答案:

答案 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>

正如您所看到的,通过将任务分解为模板以将每个节点转换为其目标,您将获得结构良好的方法。

http://xsltfiddle.liberty-development.net/nbUY4kh/2

上的在线示例