0

I have:

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>

I want to "group" this Elements with XSLT.

Each group should start with Start and should end with End My first idea was to do that with this solution: stackoverflow combining xslt issue

This would be:

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

But I think I should group with key and / or generate-id and use following-sibling and preceding-sibling

My desired output: I want to have all the Content that is precise covered by the Start and End Element.

It is not clear how to ask for the Name Start because this is one tier under the TestCaseElement wich i want to "group"?

How can I access each group if they is available some day.

Community
  • 1
  • 1
arphex
  • 180
  • 12
  • Your expected output is shown as empty. I assume that this is an editing mistake. Please correct and show expected output. Any answer given to this question will be based around xsl:for-each-group . I suggest you search on that instruction and read about it. – Sean B. Durkin Aug 01 '12 at 15:32
  • Refer http://stackoverflow.com/questions/11491108 – Sean B. Durkin Aug 01 '12 at 15:34
  • Hi, i have edited the desired Output. It unfortunately slipped outside the textblock. – arphex Aug 02 '12 at 08:46

2 Answers2

0

Something along these lines:

<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>
Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • i try to test this, the current-group selection is new to me. Outside the i need somethin like ? how is this exactly defined, the w3c output is not really example-driven... – arphex Aug 02 '12 at 08:42
  • The apply-templates here processes each node in the current group individually. You will need a template rule that matches each of those nodes (individually) and does whatever processing you want to do on that node. – Michael Kay Aug 03 '12 at 09:13
0

This XSLT 2.0 style-sheet...

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

...will take this input document, slightly adapted for clarity from your sample input, and expanded to increase test coverage range...

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

...and yield this output, as per stated requirements...

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

Notes

Notice that only the TestCaseElement elements bounded by a demarcated Start and End are retained. Other nodes outside this grouping are dropped. Also some efficiency may be gained by putting into a variable...

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

... so that this expression does not need to be re-computed for each member of the current-group().

Sean B. Durkin
  • 12,659
  • 1
  • 36
  • 65