Search code examples
c#xsltnodes

XSLT 1.0 - Multiple Child Nodes template wrapped with HTML


I am having some problems with For-Each in XSLT transform from XML. The XML contains multiple child node:

<?xml version="1.0" encoding="utf-8"?>
<testsuites duration="6376 ms">
  <testsuite>
    <testcase>
      <testid>A1</testid>
      <package>Package 1</package>
      <test>Test 1</test>
      <duration>2 ms</duration>
      <failures>0</failures>
      <pass>4</pass>
      <testparts>
        <testpart>
          <time>2020-08-23-17-03-24</time>
          <status>Test passed</status>
          <test>Assertion 1</test>
        </testpart>
        <testpart>
          <time>2020-08-23-17-03-24</time>
          <status>Test passed</status>
          <test>Assertion 2</test>
        </testpart>
        <testpart>
          <time>2020-08-23-17-03-24</time>
          <status>Test passed</status>
          <test>Assertion 3</test>
        </testpart>
      </testparts>
    </testcase>
  </testsuite>
  .......

and the XSLT file is:

<?xml version="1.0" encoding="utf-8"?> 
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta charset="utf-8" />
    ...Some styles and scripts
  </head>
  <body>
    <div>
        <xsl:for-each select="testsuites/testsuite/testcase">
            <span class="column1"><xsl:value-of select="duration"/></span>
            <span class="PackageStatus"><xsl:value-of select="package"/></span>
            <span class="Function"><xsl:value-of select="test"/></span>
            <span class="Message" name="ID0AFH0IHId"><xsl:value-of select="failures"/></span>
            <span class="Message" name="ID0AFH0IHId"><xsl:value-of select="pass"/></span>
            <span class="Message" name="ID0AFH0IHId"><xsl:value-of select="pass"/>Show Assertions</span>
            
            <div>
                <xsl:for-each select="testsuites/testsuite/testcase/testparts/testpart">
                  <span class="column1"><xsl:value-of select="time"/></span>
                  <span class="passed"><xsl:value-of select="status"/></span>
                  <span class="Function"><xsl:value-of select="test"/></span>
              </xsl:for-each>
            </div>
        </xsl:for-each>
    </div>
</body>
</html>

You can see there are muliple testcase and beneath that, testparts have multiple testpart element. Now the first foreach is working as expected, but the inner one is not working


Solution

  • This is more of a general XML question but for a more complete answer than my comment above I refer to the XSLT documentation regarding focus that says:

    [Definition: The context item is the item currently being processed. An item (see [XDM 3.0]) is either an atomic value (such as an integer, date, or string), a node, or a function item. It changes whenever instructions such as xsl:apply-templates and xsl:for-each are used to process a sequence of items; each item in such a sequence becomes the context item while that item is being processed.] The context item is returned by the XPath expression . (dot).

    So when you enter the first for-each the context has changed and you need to apply further selections relative to that context, for for your example it's enough to change from the absolute path to the relative path of the selection for the inner loop:

    <xsl:for-each select="testparts/testpart">