Skip Navigation LinksHome Page > Forums > SpiraTeam Forums > Spira Custom Reports > Design traceability withi...
For a project in regulated environment I need to create a custom report showing that the requirements are propagating through software design and software architecture.
To achieve this, in the software Requirements Artifact area I've created the following structure:
SRS Requirement 1 Requirement 2 Requirement 3SAD Architecture 1 Architecture 2SDD Design 1 Design 2 Design 3 Design 4The Requirements artifacts got Component set to "Requirements", Architecture ones are "Architecture" and Design ones are set to "Design".
This is the report I want to get in the end:
This way I could easily check if there is a gap in design traceability (it would be even nicer if I could paint the empy cell in a different colour, but can live without it).
Question -how can I achieve that? I understand that I need somehow to access the component record of the linked artifact, but not quite sure how?
Can you please help me to change the code below so that it'll work as intended?
<td> <xsl:value-of select="Name"/> </td> <td> <xsl:if test="Requirements/ArtifactLink"> <xsl:for-each select="Requirements/ArtifactLink"> <xsl:if test="position() > 1 and ArtifactLink/Component = Architecture">, <br /> </xsl:if> <xsl:value-of select="ArtifactLinkTypeName"/> </xsl:for-each> </xsl:if> </td> <td> <xsl:if test="Requirements/ArtifactLink"> <xsl:for-each select="Requirements/ArtifactLink"> <xsl:if test="position() > 1 and ArtifactLink/Component = Design">, <br /> </xsl:if> <xsl:value-of select="ArtifactLinkTypeName"/> </xsl:for-each> </xsl:if> </td>
Hello,
I think this Knowledge Base article should help you to achieve this:
Creating a Custom Report with Grouped Headings
Regards,Victoria -
Hi Victoria,
Thank you for your response.
I've looked at the KB but I am not sure if it'll actually solve the issue as I need to access not the Component itself but component of each linked requirement. Or, in pseudo-code:
FOR AllRequirements PRINT RequirementName in Column1 IF LinkedRequirements != 0 THEN READ LinkedRequirement IF LinkedRequirement.Component = "Architecture" PRINT LinkedRequirement.Name in Column2 IF LinkedRequirement.Component = "Design" PRINT LinkedRequirement.Name in Column3 ENDIFENDFOR
Or am I missing something?
I think this article will help you to achieve what you're trying to get: Building a Component-Based Traceability Matrix in Spira Using Custom ESQL and XSLT
Thank you very much for your help.
I've created the report as per you KB and the results aren't quite what I was expecting.
Expectations:
Report output:
To make it clear, the associations are as follows:All requirements in SRS section have component set to "Requirements"), in SAD to "Architecture" and in SDD to "Design"
Right, spent some time with Grok and Claude and here's the solution.
The issue is that the KB is assuming that the associations are ALWAYS done from the same end (from Requirements to Architecture and Design). If any of the artifacts are linked other way round (which is normal), then it won't work.
Here's the updated ESQL:
SELECT RQ.REQUIREMENT_ID, RQ.NAME AS REQUIREMENT_NAME, RQ.COMPONENT_NAME AS BASE_COMPONENT, LR.NAME AS LINKED_NAME, LR.COMPONENT_NAME AS LINKED_COMPONENT FROM SpiraTestEntities.R_Requirements AS RQ LEFT JOIN SpiraTestEntities.R_ArtifactAssociations AS AA ON AA.SOURCE_ARTIFACT_TYPE_ID = 1 AND AA.DEST_ARTIFACT_TYPE_ID = 1 AND ( (RQ.REQUIREMENT_ID = AA.SOURCE_ARTIFACT_ID) OR (RQ.REQUIREMENT_ID = AA.DEST_ARTIFACT_ID) ) LEFT JOIN SpiraTestEntities.R_Requirements AS LR ON LR.IS_DELETED = False AND LR.COMPONENT_NAME != 'Requirements' AND ( (AA.DEST_ARTIFACT_ID = LR.REQUIREMENT_ID AND RQ.REQUIREMENT_ID = AA.SOURCE_ARTIFACT_ID) OR (AA.SOURCE_ARTIFACT_ID = LR.REQUIREMENT_ID AND RQ.REQUIREMENT_ID = AA.DEST_ARTIFACT_ID) ) WHERE RQ.PROJECT_ID = ${ProjectId} AND RQ.IS_DELETED = False AND RQ.COMPONENT_NAME = 'Requirements'
The XSLT shall be updated too:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:key name="ReqGroup" match="*[REQUIREMENT_ID]" use="REQUIREMENT_ID" /> <!-- Only treat non-Requirements components as column headers --> <xsl:key name="ComponentGroup" match="*[string-length(LINKED_COMPONENT) > 0 and LINKED_COMPONENT != 'Requirements']" use="LINKED_COMPONENT" /> <xsl:template match="/"> <table class="DataGrid" style="width:100%"> <tr> <th>Requirement Name</th> <xsl:for-each select="//*[string-length(LINKED_COMPONENT) > 0 and LINKED_COMPONENT != 'Requirements'] [generate-id() = generate-id(key('ComponentGroup', LINKED_COMPONENT)[1])]"> <xsl:sort select="LINKED_COMPONENT" /> <th> <xsl:value-of select="LINKED_COMPONENT"/> </th> </xsl:for-each> </tr> <xsl:for-each select="//*[REQUIREMENT_ID][generate-id() = generate-id(key('ReqGroup', REQUIREMENT_ID)[1])]"> <xsl:variable name="CurrentReqID" select="REQUIREMENT_ID" /> <tr> <td> <xsl:value-of select="REQUIREMENT_NAME"/> </td> <xsl:for-each select="//*[string-length(LINKED_COMPONENT) > 0 and LINKED_COMPONENT != 'Requirements'] [generate-id() = generate-id(key('ComponentGroup', LINKED_COMPONENT)[1])]"> <xsl:sort select="LINKED_COMPONENT" /> <xsl:variable name="CurrentColComponent" select="LINKED_COMPONENT" /> <td> <xsl:for-each select="key('ReqGroup', $CurrentReqID)[LINKED_COMPONENT = $CurrentColComponent]"> <xsl:if test="position() > 1">, <br /></xsl:if> <xsl:value-of select="LINKED_NAME"/> </xsl:for-each> </td> </xsl:for-each> </tr> </xsl:for-each> </table> </xsl:template> </xsl:stylesheet>
As a result, the following report will be generated (note: not all of the requirements in the project got associations, to test the Gap Analysis functionality)
Architecture 2
Maybe the KB should be updated too?
Thank you very much for your valuable input! It is very helpful indeed.
And if you have any questions, please email or call us at +1 (202) 558-6885