1

I have some XSLT that should output a single piece of PLAIN text dependent on values within the input XML document.

I have a template-match clause which filters out SIStatusHistory nodes when a 'Status' value within that node has a value of 'SRequested' OR 'SCreated'. I don't want those nodes to be evaluated.

EDIT:

For example the sub node list:

 <SIHistories>
        <SIStatusHistory>
            <Created>2019-09-10T12:55:45.613</Created>
            <SIStat>
                <ServiceInstanceStatusId>5</ServiceInstanceStatusId>
                <Status>SRequested</Status>
            </SIStat>
        </SIStatusHistory>
        <SIStatusHistory>
            <Created>2019-09-10T13:06:37.153</Created>
            <SIStat>
                <ServiceInstanceStatusId>5</ServiceInstanceStatusId>
                <Status>SRejected</Status>
            </SIStat>
        </SIStatusHistory>
        <SIStatusHistory>
            <Created>2019-09-10T15:14:56.28</Created>
            <SIStat>
                <ServiceInstanceStatusId>5</ServiceInstanceStatusId>
                <Status>SRequested</Status>
            </SIStat>
        </SIStatusHistory>
    </SIHistories>

Should be pared down to:

 <SIHistories>      
        <SIStatusHistory>
            <Created>2019-09-10T13:06:37.153</Created>
            <SIStat>
                <ServiceInstanceStatusId>5</ServiceInstanceStatusId>
                <Status>SRejected</Status>
            </SIStat>
        </SIStatusHistory>
    </SIHistories>

...and then evaluated for Status='SRejected'

When the first SIStatusHistory node has a Status of 'SRejected' OR RAddress = 'No' this should be output:

"CheckQueue"

Otherwise, output:

"CompQueue"

The Issue I am having is that the XSLT seems to be executing multiple times for each sub-node in my template-match clause.

So (for example) instead of

CompQueue

I'm getting the output:

"CompQueueCompQueue"

Any ideas?

Input XML:

<SForm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://test/p/s/types">
<SFID>00000</SFID>
<SID>00000</SID>
<FData>
    <FPH>
        <RAddress>No</RAddress>
        <FaultDescription>Text</FaultDescription>
        <Channel>P</Channel>
        <Customer/>
    </FPH>
    <ApplicantExt>
        <HasCommercialUse>Yes</HasCommercialUse>
    </ApplicantExt>
</FData>
<SIFormCounters />
<CompDate>2019-09-10T13:05:18.883</CompDate>
<SIHistories>
    <SIStatusHistory>
        <Created>2019-09-10T12:55:45.613</Created>
        <SIStat>
            <ServiceInstanceStatusId>5</ServiceInstanceStatusId>
            <Status>SRequested</Status>
        </SIStat>
    </SIStatusHistory>
    <SIStatusHistory>
        <Created>2019-09-10T13:06:37.153</Created>
        <SIStat>
            <ServiceInstanceStatusId>5</ServiceInstanceStatusId>
            <Status>SRejected</Status>
        </SIStat>
    </SIStatusHistory>
    <SIStatusHistory>
        <Created>2019-09-10T15:14:56.28</Created>
        <SIStat>
            <ServiceInstanceStatusId>5</ServiceInstanceStatusId>
            <Status>SRequested</Status>
        </SIStat>
    </SIStatusHistory>
</SIHistories>

XSLT:

 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:pst="http://test/p/s/types" exclude-result-prefixes="pst" version="1.0">
  <xsl:output method="text" indent="no" />
 <xsl:template match="text()" />
  <xsl:template match="pst:SForm/pst:SIHistories/pst:SIStatusHistory[pst:SIStat/pst:Status='SCreated' or pst:SIStat/pst:Status='SRequested']">
   <xsl:choose>
      <xsl:when test="pst:SIHistories/pst:SIStatusHistory[1]/pst:SIStat/pst:Status = 'SRejected'">
        <xsl:text>CheckQueue</xsl:text>
      </xsl:when>
      <xsl:when test="pst:FormData/pst:FPH/pst:RAddress = 'No'">
        <xsl:text>CheckQueue</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>CompQueue</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>
2
  • Please post desired output which will illustrate the hard to read explanation at the top. Commented Sep 19, 2019 at 18:28
  • Desired output is as described - the plain text: CheckQueue Commented Sep 19, 2019 at 19:06

2 Answers 2

1

I need that to remove all nodes that have the value SCreated and SRequested, before we evaluate if the first node is SRejected.

I believe that could be implemented as:

<xsl:template match="SIHistories">
    <xsl:variable name="first-status" select="SIStatusHistory[not(SIStat/Status='SCreated' or SIStat/Status='SRequested')][1]/SIStat/Status" />
    <xsl:choose>
        <xsl:when test="$first-status='SRejected'">CheckQueue</xsl:when>
        <xsl:otherwise>CompQueue</xsl:otherwise>
    </xsl:choose>
</xsl:template>
Sign up to request clarification or add additional context in comments.

1 Comment

Bingo. This works - and it makes sense now. I just had to add the namespaces in and add the check on the RAddress field back into the when-otherwise and it functions as needed. Thank you.
1

Currently there are two elements for your template match with condition pst:Status='SRequested'. Since you intend to check the first, adjust template using position()=1 on first node. Additionally, you need to invoke ancestor::* or walk up the tree to check the FData condition

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:pst="http://test/p/s/types" 
                exclude-result-prefixes="pst" version="1.0">
    <xsl:output method="text" indent="no" />
    <xsl:template match="text()" />

    <xsl:template match="pst:SForm/pst:SIHistories/pst:SIStatusHistory[position()=1 and (pst:SIStat/pst:Status='SCreated' or pst:SIStat/pst:Status='SRequested')]">
        <xsl:choose>
          <xsl:when test="pst:SIHistories/pst:SIStatusHistory[1]/pst:SIStat/pst:Status = 'SRejected'">
            <xsl:text>CheckQueue</xsl:text>
          </xsl:when>
          <xsl:when test="ancestor::pst:SForm/pst:FData/pst:FPH/pst:RAddress = 'No'">
            <xsl:text>CheckQueue</xsl:text>
          </xsl:when>
          <xsl:otherwise>
            <xsl:text>CompQueue</xsl:text>
          </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

1 Comment

Thank you for your help. The only issue here is that I think that having postion()=1 in the template match call means it is only applying the removal of the two values SRequested and SCreated to the first node. Whereas I need that to remove all nodes that have the value SCreated and SRequested, before we evaluate if the first node is SRejected.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.