按顺序转换XML节点

按顺序转换XML节点,xml,xslt,Xml,Xslt,XML输入: <a> <b>text_b</b> <d>text_d</d> <c>text_c</c> <e>text_e</e> <d>text_d</d> <f>text_f</f> </a> <g> <b>text_b</b>

XML输入:

<a>
    <b>text_b</b>
    <d>text_d</d>
    <c>text_c</c>
    <e>text_e</e>
    <d>text_d</d>
    <f>text_f</f>
</a>
<g>
    <b>text_b</b>
    <d>text_d</d>
    <c>text_c</c>
    <e>text_e</e>
    <d>text_d</d>
    <f>text_f</f>
</g>
期望输出:

<aa>
    <aaa>
        <some_extra_tag>some_text</some_extra_tag>
        <aab>text_b</aab>
    </aaa>
    <aad>text_d</aad>
    <aaa>
        <some_extra_tag>some_text</some_extra_tag>
        <aac>text_c</aac>
        <aae>text_e</aae>
    </aaa>
    <aad>text_d</aad>
    <aaa>
        <some_extra_tag>some_text</some_extra_tag>
        <aaf>text_f</aaf>
    </aaa>
</aa>
<gg>
    <aab>text_b</aab>
    <ggg>
        <some_extra_tag2>some_text</some_extra_tag2>
        <aad>text_d</aad>
    </ggg>
    <aac>text_c</aac>
    <aae>text_e</aae>
    <ggg>
        <some_extra_tag2>some_text</some_extra_tag2>
        <aad>text_d</aad>
    </ggg>
    <aaf>text_f</aaf>
</gg>
我可以使用XSLT将上述XML输入转换为所需的输出吗? 限制: 一些额外的标签应该由a-tag-Template生成,一些额外的标签2-tag应该由g-tag-Template生成。

XSLT

  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
        <xsl:output method="xml" indent="yes"/>

      <xsl:template match="outer">
        <doc>
          <xsl:apply-templates select="*" />
        </doc>
      </xsl:template>


      <xsl:template match="*">
        <outer>
          <span>
            <xsl:copy-of select="."/>
          </span>
        </outer>
      </xsl:template>

    </xsl:stylesheet>
输出:

<?xml version="1.0" encoding="utf-8"?>
<doc>
  <outer>
    <span>
      <inner>text first</inner>
    </span>
  </outer>
  <outer>
    <span>
      <middle>text second</middle>
    </span>
  </outer>
  <outer>
    <span>
      <inner>text third</inner>
    </span>
  </outer>
</doc>

我认为你想做的有点棘手,但我相信下面的内容可以做到。它通过使用递归模板工作:

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

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

  <xsl:template match="outer">
    <xsl:copy>
      <xsl:apply-templates select="*[not(self::inner)] |
                                   inner[not(preceding-sibling::*[1][self::inner])]" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="inner[not(preceding-sibling::*[1][self::inner])]">
    <span>
      <xsl:call-template name="Copy" />
      <xsl:apply-templates select="following-sibling::*[1][self::inner]" />
    </span>
  </xsl:template>

  <xsl:template match="inner">
    <xsl:call-template name="Copy" />
    <xsl:apply-templates select="following-sibling::*[1][self::inner]" />
  </xsl:template>

</xsl:stylesheet>
在该输入上运行时:

<outer>
  <inner>text first</inner>
  <inner>text second</inner>
  <middle>text third</middle>
  <inner>text fourth</inner>
</outer>
它会产生以下结果:

<outer>
  <span>
    <inner>text first</inner>
    <inner>text second</inner>
  </span>
  <middle>text third</middle>
  <span>
    <inner>text fourth</inner>
  </span>
</outer>

你是说你想把每个内部和中间部分放在它自己的外部元素中,把内部部分放在跨度内?你还没有真正解释你想做什么。我想做的实际上只是保持原来的顺序,我知道如果我使用,将保持顺序,但是我不能这样做,因为是在外部模板上生成的。实际上,中间标记是否有自己的外部标记并不重要。为了澄清,我有一个编辑我的问题。你的问题仍然不清楚。这个例子模棱两可-转换的规则是什么?@michael.hor257k现在足够清楚了吗?很抱歉,问题始终不够清楚,因为我真的不想包含详细信息。您的输出既不匹配当前请求的输出,也不匹配原始请求的输出。为什么?我的输出有什么问题?为使XML有效而添加的Doc标记,似乎有一些错误,我确实提到需要在外部标记上生成span标记,对吗?@sstept当我的XSLT生成您在所需输出下列出的输出时。如果您想要的输出是其他内容,请澄清并解释您的要求。是的,它确实产生了正确的输出,但是它忽略了我的要求我已经编辑了我的question@sstephen我需要通过外部标记生成span标记是什么意思?你能提供一个我的解决方案不能产生所需结果的输入和输出吗?请更仔细地阅读我的问题,我已经为它写了一个简单的例子,即在下面,比如:。我想我把问题简化了,这是我的要求,而你的答案不合适的情况:在内部标签旁边有inner2标签,它们都需要在同一个跨度标签内。。。文本文本。。。