【问题标题】:XSLT copy starting from certain node从某个节点开始的 XSLT 复制
【发布时间】:2014-06-19 23:48:12
【问题描述】:

我想使用 XSLT 将 XML 文件的一部分移动到另一个节点。 我只想移动从某个节点开始的所有内容。 最好通过例子来说明。

这将是输入 XML(这只是一个示例)

<Messages>
  <Message>
    <Header>
        <Name>Message Content 1</Name>
    </Header>
    <Info1>
        <Description>blabla</Description>
    </Info1>
    <Info2>
        <Name>Test</Name>
        <Description>blabla</Description>
    </Info2>
    ... Possible more nodes (with random names)
    <Header>
        <Name>Message Content Summary</Name>
    </Header>
    <Info1>
        <Total>blablabla</Total>
    </Info1>
    ... Possible more nodes (with random names)
  </Message>
</Messages>

我想得到以下输出:

<Messages>
  <Message>
    <Header>
        <Name>Message Content 1</Name>
    </Header>
    <Info1>
        <Description>blabla</Description>
    </Info1>
    <Info2>
        <Name>Test</Name>
        <Description>blabla</Description>
    </Info2>
    ... Possible more nodes (with random names)
  </Message>
  <MessageSummary>
    <Header>
        <Name>Message Content Summary</Name>
    </Header>
    <Info1>
        <Total>blablabla</Total>
    </Info1>
    ... Possible more nodes (with random names)
  </MessageSummary>
</Messages>

所以我想从节点“Header”的最后一次出现开始将所有内容移动到单独的节点“MessageSummary”中。

我有什么方法可以使用 XSLT 1.0 完成此任务吗? 任何帮助将不胜感激。

谢谢。

【问题讨论】:

    标签: xml xslt-1.0


    【解决方案1】:

    因此,当您处于输入 Message 元素的上下文中时,您希望将其后至少有一个 Header 的任何元素放入输出 Message 以及 MessageSummary 内的所有其他元素。您可以将这两种情况区分为*[following-sibling::Header]*[not(following-sibling::Header)],所以如果我们从标准身份转换开始,我们最终会得到

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:strip-space elements="*" />
      <xsl:output indent="yes" />
    
      <!-- identity template - copies everything as-is unless overridden -->
      <xsl:template match="@*|node()">
        <xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
      </xsl:template>
    
      <xsl:template match="Message">
        <xsl:copy>
          <xsl:apply-templates select="*[following-sibling::Header]" />
        </xsl:copy>
        <MessageSummary>
          <xsl:apply-templates select="*[not(following-sibling::Header)]" />
        </MessageSummary>
      </xsl:template>
    </xsl:stylesheet>
    

    如果您在“随机名称”部分中有其他名为 Message 的元素,您可能希望使此模板更具体,例如

      <xsl:template match="Messages/Message">
    

    所以它只捕获你真正想要的元素。

    【讨论】:

    • 您好,感谢您的建议。我对其进行了一些修改,因此第一个副本选择 *[following-sibling::Header[1]] ==> 需要复制第一个标题下的所有项目。第二个副本选择:*[not(following-sibling::Header[2])] ==> 第二个标题下的所有项都需要复制到汇总节点。它似乎工作正常:)
    • @Rise_against 不会完全按照您的描述进行,因为同级轴上的数字谓词计算同级 - *[not(following- sibling::Header[2])] 查找在它们之后至少有两个标题的所有元素,因此之前的元素倒数第二个标题,不一定是第二个。如果您想使用第二个标题作为截止点,那么您需要在第一部分使用 Header[2]/preceding-sibling::*,在第二部分使用 Header[2] | Header[2]/following-sibling::*
    • 嗨伊恩,你是对的!忘记我的最后一句话,您的解决方案工作正常!起初它不起作用是我的错(在 XSLT 中出现了一些拼写错误)。但修正后,它按预期工作。再次感谢您的帮助!
    猜你喜欢
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-10
    • 1970-01-01
    相关资源
    最近更新 更多