Question

my xml file

<?xml version="1.0" encoding="UTF-8"?>
<tests>
<testrun run="test1">
    <test name="foo" pass="true" />
    <test name="bar" pass="true" />
    <test name="baz" pass="true" />
</testrun>
<testrun run="test2">
    <test name="foo" pass="true" />
    <test name="bar" pass="false" />
    <test name="baz" pass="false" />
        <testrun run="test2.1">
            <test name="foo" pass="true" />
            <test name="bar" pass="false" />
            <test name="baz" pass="false" />
        </testrun>
</testrun>
<testrun run="test3">
    <test name="foo" pass="false" />
    <test name="bar" pass="true" />
    <test name="baz" pass="false" />
</testrun>
</tests>

my xsl file

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
version="2.0">

<xsl:output method="text"/>
<xsl:output method="html" indent="yes" name="html"/>

<xsl:template match="/">
 <xsl:for-each select="//testrun">
  <xsl:variable name="filename"
   select="concat('output1/',@run,'.html')" />
   <xsl:value-of select="$filename" /> 
    <xsl:result-document href="{$filename}" format="html">
     <html><body>
     <xsl:value-of select="@run"/>
     </body></html>
   </xsl:result-document>
 </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

In output I get four documents (test1, test2, test2.1, test3). Is it possible to create only three files (test1, test2, test3) where test2 contains values ​​test2.1?

Was it helpful?

Solution

Here's one way to do it:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">

  <xsl:output method="text"/>
  <xsl:output method="html" indent="yes" name="html"/>

  <!-- There's no need for a for-each loop. Just match all the
       testruns that are immediate children of tests -->
  <xsl:template match="/tests/testrun">
    <xsl:variable name="filename"
                  select="concat('output1/',@run,'.html')" />
    <xsl:value-of select="$filename" />
    <xsl:result-document href="{$filename}" format="html">
      <html><body>
        <xsl:value-of select="@run"/>
        <!-- You need to adapt this to your specific needs. -->
        <xsl:apply-templates select="test"/>
        <xsl:apply-templates select="testrun"/>
      </body></html>
    </xsl:result-document>
  </xsl:template>

  <!-- These templates are here mostly for illustration
       purposes. You'd have to decide that you actually want to do
       with your data. -->
  <xsl:template match="test">
    <p>test: <xsl:value-of select="@name"/></p>
  </xsl:template>

  <xsl:template match="testrun/testrun">
    <p>testrun: <xsl:value-of select="@run"/></p>
    <xsl:apply-templates select="test"/>
  </xsl:template>
</xsl:stylesheet>

The output/test2.html file will contain:

<html>
   <body>test2
      <p>test: foo</p>
      <p>test: bar</p>
      <p>test: baz</p>
      <p>testrun: test2.1</p>
      <p>test: foo</p>
      <p>test: bar</p>
      <p>test: baz</p>
   </body>
</html>

(If you edit the tests in test2.1 to change the names so that they don't repeat those of test2, you'll be able to clearly see that the foo, bar, baz after test2.1 are those of test2.1.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top