【问题标题】:Group Nodes / content with preceding-sibling and following-sibling使用前同级和后同级分组节点/内容
【发布时间】:2012-08-01 14:50:36
【问题描述】:

我有:

XML

<TestCases>
   <TestCase>
       <TestCaseElement>
                    <Name><![CDATA[Start]]></Name>
                    <Role><![CDATA[TESTSTEP]]></Role>
       </TestCaseElement>
       <TestCaseElement>
                    <Name><![CDATA[Content]]></Name>
                    <Role><![CDATA[TESTSTEP]]></Role>
                    <Code>
                       <Line><![CDATA[some Content]></Line>
                       <Line><![CDATA[some Content]></Line>
                    </Code>

       </TestCaseElement>
       <TestCaseElement>
                   <Name><![CDATA[End]]></Name>
                   <Role><![CDATA[TESTSTEP]]></Role>
       </TestCaseElement>
     **n of these Start-Content-Stop Triplets are in the XML Document**
  </TestCase>
</TestCases>

我想用 XSLT 对这些元素进行“分组”。

每个组应以 Start 开头,并应以 End 结尾 我的第一个想法是用这个解决方案做到这一点:stackoverflow combining xslt issue

这将是:

<xsl:for-each select="/TestCases/TestCase/TestCaseElement[../TestCaseElement[Name='Step-Start'] << . and . >> ../TestCaseElement[Name='Step-End']]">

但我认为我应该与 key 和/或 generate-id 分组并使用 following-siblingpreceding-sibling

我想要的输出:我希望所有内容都被开始和结束元素精确覆盖。

不清楚如何询问名称 Start,因为这是我想要“分组”的 TestCaseElement 下的一层?

如果某天有空,我如何访问每个组。

【问题讨论】:

  • 您的预期输出显示为空。我认为这是一个编辑错误。请更正并显示预期输出。对此问题的任何回答都将基于 xsl:for-each-group 。我建议您搜索该说明并阅读它。
  • 嗨,我已经编辑了所需的输出。不幸的是,它滑出了文本块。

标签: xml xslt xpath xslt-2.0


【解决方案1】:

类似的东西:

<xsl:template match="TestCase">
  <xsl:for-each-group select="TestCaseElement" group-starting-with="*[Name='Start']">
    <group>
      <xsl:apply-templates select="current-group()"/>
    </group>
  </xsl:for-each-group>
</xsl:template>

【讨论】:

  • 我尝试对此进行测试,当前组选择对我来说是新的。在
  • 这里的应用模板分别处理当前组中的每个节点。您将需要一个与每个节点(单独)匹配的模板规则,并在该节点上执行您想要执行的任何处理。
【解决方案2】:

这个 XSLT 2.0 样式表...

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xsl xs">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />

<xsl:template match="TestCase">
 <xsl:copy>
  <xsl:apply-templates select="@*" />
  <xsl:for-each-group select="TestCaseElement" group-starting-with="*[Name='Start']">
   <xsl:apply-templates select="current-group()
     [not(. >> current-group()/self::*[Name='End'])]"/>
  </xsl:for-each-group>
 </xsl:copy>
</xsl:template>

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

</xsl:stylesheet>

...将采用此输入文档,根据您的示例输入略微调整以提高清晰度,并扩展以增加测试覆盖范围...

<TestCases>
    <TestCase>
        <TestCaseElement>
            <Name>Start</Name>
            <Role>TESTSTEP 1</Role>
        </TestCaseElement>
        <TestCaseElement>
            <Name>Content 1</Name>
            <Role>TESTSTEP</Role>
            <Code>
                <Line>some Content 1</Line>
                <Line>some Content 1</Line>
            </Code>
        </TestCaseElement>
        <TestCaseElement>
            <Name>End</Name>
            <Role>TESTSTEP 1</Role>
        </TestCaseElement>
        <TestCaseElement>
            This content is dropped because it is
            not between a Start and End TestCaseElement.
        </TestCaseElement>
        <TestCaseElement>
            <Name>Start</Name>
            <Role>TESTSTEP 2</Role>
        </TestCaseElement>
        <TestCaseElement>
            <Name>Content 2</Name>
            <Role>TESTSTEP</Role>
            <Code>
                <Line>some Content 2</Line>
                <Line>some Content 2</Line>
            </Code>
        </TestCaseElement>
        <TestCaseElement>
            <Name>End</Name>
            <Role>TESTSTEP 2</Role>
        </TestCaseElement>
    </TestCase>
</TestCases> 

...并根据规定的要求产生此输出...

<TestCases>
   <TestCase>
      <TestCaseElement>
         <Name>Start</Name>
         <Role>TESTSTEP 1</Role>
      </TestCaseElement>
      <TestCaseElement>
         <Name>Content 1</Name>
         <Role>TESTSTEP</Role>
         <Code>
            <Line>some Content 1</Line>
            <Line>some Content 1</Line>
         </Code>
      </TestCaseElement>
      <TestCaseElement>
         <Name>End</Name>
         <Role>TESTSTEP 1</Role>
      </TestCaseElement>
      <TestCaseElement>
         <Name>Start</Name>
         <Role>TESTSTEP 2</Role>
      </TestCaseElement>
      <TestCaseElement>
         <Name>Content 2</Name>
         <Role>TESTSTEP</Role>
         <Code>
            <Line>some Content 2</Line>
            <Line>some Content 2</Line>
         </Code>
      </TestCaseElement>
      <TestCaseElement>
         <Name>End</Name>
         <Role>TESTSTEP 2</Role>
      </TestCaseElement>
   </TestCase>
</TestCases>

注意事项

请注意,仅保留由划分的 Start 和 End 界定的 TestCaseElement 元素。此分组之外的其他节点将被删除。也可以通过放入变量来获得一些效率...

current-group()/self::*[Name='End']

... 这样就不需要为 current-group() 的每个成员重新计算这个表达式。

【讨论】:

    猜你喜欢
    • 2012-04-10
    • 1970-01-01
    • 2016-08-19
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-25
    • 1970-01-01
    相关资源
    最近更新 更多