Question

Given a node, eg.

<SI elem1="TI" elem2="FN" elem3="4099450222" elem4="TM" elem5="4094110000" elem6="MT" elem7="SP" elem8="MC" elem9="DS" elem10="DA" elem11="16"/>

I need my output to be "DA" if any attribute is "DA", or the value of the next attribute if any attribute is "BA" (i.e. if elem7="BA elem8="03" I want "03" output)

There is no danger of multiple matches, so if an attribute is "BA", there will be no "DA" attribute, but the values could occur in any element

I've looked into the attribute:: tag, but I'm not sure if this will fulfil my needs.

any help greatly appreciated

Was it helpful?

Solution

I made an assumption that your attributes has names in form of elemN where N = 1,2,3..., and they are ordered accordingly.

The following XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="text" />
    <xsl:template match="/SI">
        <xsl:choose>
            <xsl:when test="some $i in @* satisfies $i='DA'">
                <xsl:text>DA</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:variable name="attr" select="concat('elem', xs:decimal(substring-after(@*[.='BA']/name(), 'elem')) + 1)" />
                <xsl:value-of select="@*[name() = $attr]" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

applied to the following input XML:

<?xml version="1.0" encoding="UTF-8"?>
<SI elem1="TI" elem2="FN" elem3="4099450222" elem4="TM" elem5="4094110000" elem6="MT" elem7="SP" elem8="MC" elem9="DS" elem10="DA" elem11="16" />

gives DA as the output.

And applied to the following XML:

<?xml version="1.0" encoding="UTF-8"?>
<SI elem1="TI" elem2="FN" elem3="4099450222" elem4="TM" elem5="4094110000" elem6="MT" elem7="BA" elem8="03" elem9="DS" elem10="DAs" elem11="16" />

gives 03 as the output.

EDIT

Here's the XSLT 1.0 version (tested under Altova XMLSpy):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" />
    <xsl:template match="/">
        <xsl:apply-templates select="SI/@*" />
    </xsl:template>

    <xsl:template match="@*">
        <xsl:choose>
        <xsl:when test=". = 'DA'">
            <xsl:text>DA</xsl:text>     
        </xsl:when>
        <xsl:when test=".='BA'">
            <xsl:variable name="attr" select="concat('elem', substring-after(name(), 'elem') + 1)" />
            <xsl:value-of select="/SI/@*[name() = $attr]" />
        </xsl:when>
        <xsl:otherwise/>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

OTHER TIPS

I need my output to be "DA" if any attribute is "DA", or the value of the next attribute if any attribute is "BA" (i.e. if elem7="BA elem8="03" I want "03" output)

There is no danger of multiple matches, so if an attribute is "BA", there will be no "DA" attribute, but the values could occur in any element

This single XPath expression produces the wanted value:

  string(/*/@*[. = 'DA']
        |
         /*/@*[name()
              =
               concat('elem', substring-after(name(/*/@*[.='BA']), 'elem') +1)]
         )

And here is the complete transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:template match="/">
     <xsl:copy-of select=
     "string(/*/@*[. = 'DA']
            |
             /*/@*[name()
                  =
                   concat('elem', substring-after(name(/*/@*[.='BA']), 'elem') +1)]
             )"/>
 </xsl:template>
</xsl:stylesheet>

As can be seen this transformation simply evaluates the XPath expression and copies the result of the evaluation to the output.

When the transformation is applied on this XML document (your 2nd case):

<SI elem1="TI"
    elem2="FN"
    elem3="4099450222"
    elem4="TM"
    elem5="4094110000"
    elem6="MT"
    elem7="BA"
    elem8="03"
    elem9="DS"
    elem10="DD"
    elem11="16"/>

the result is:

03

When the same transformation is applied on the originally provided XML document (your 1st case):

<SI elem1="TI"
    elem2="FN"
    elem3="4099450222"
    elem4="TM"
    elem5="4094110000"
    elem6="MT"
    elem7="SP"
    elem8="MC"
    elem9="DS"
    elem10="DA"
    elem11="16"/>

again the wanted, correct result is produced:

DA

Explanation:

Proper use of the XPath union operator |, and the functions string(), substring-after(), name() and `concat().

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