Reputation: 77
I winded up doing some xsl transformations on .xml, I managed to do somewhat of what I would like to do, but I can't figure out the rest. This is the .xml content
<Parent1>
<Parent2>
<Number>"100"</Number>
<Name>"SanJose"</Name>
<Type>"SanJoseExtra"</Type>
<Adress>Avenue 54</Adress>
<Status>2</Status>
<TR5>1</TR5>
<TR10>0</TR10>
<Modifier>0</Modifier>
</Parent2>
<Parent2>
<Number>"100"</Number>
<Name>"SanTropez"</Name>
<Type>"SanTropezSmall"</Type>
<Adress>British Cal 3</Adress>
<Status>2</Status>
<TR5>1</TR5>
<TR10>1</TR10>
<Modifier>0</Modifier>
</Parent2>
<Parent2>
<Number>"101"</Number>
<Name>"SanJose"</Name>
<Type>"SanDiegoMedium"</Type>
<Adress>French Revolution n.n.</Adress>
<Status>2</Status>
<TR5>1</TR5>
<TR10>1</TR10>
<Modifier>0</Modifier>
</Parent2>
<Parent2>
<Number>"100"</Number>
<Name>"SanJose"</Name>
<Type>"SanJoseSmall"</Type>
<Adress>Avenue 54</Adress>
<Status>1</Status>
<TR5>1</TR5>
<TR10>0</TR10>
<Modifier>0</Modifier>
</Parent2>
</Parent1>
and I would like to change the Modifier value to 1 if the <Name>
contains SanJose and the <Status>
contains 1. So I made something like this to get this output :
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="XMLLine[contains(./Name,'SanJose') and contains(./Status,'1')]">
<Parent2>
<xsl:copy-of select="Number" />
<xsl:copy-of select="Name" />
<xsl:copy-of select="Type" />
<xsl:copy-of select="Adress" />
<xsl:copy-of select="Status" />
<xsl:copy-of select="TR5" />
<xsl:copy-of select="TR10" />
<Modifier>1</Modifier>
</Parent2>
</xsl:template>
</xsl:stylesheet>
But then I realized that there is SanJose with status 1 where I also want to change the Modifier to 1, but I don't have anything connecting it other than Name which I know in advance and the 100 which I don't always know in advance because the list goes on.
So to sum it up, the problem I find is that I have common name and status which I can use but I also want to apply it to other nodes containing name SanJose but with the same Number which I can't know in advance.
EDIT: Adding an increment for every occurrence with the same Number. So instead of changing the Modifier to 1 I was trying to make it STATUS1, STATUS2, STATUS3.... and so on. I tried modifying your xsl:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="incre">0</xsl:variable>
<xsl:key name="matching-parent" match="Parent2[Name='SanJose' and Status=1]" use="Number" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Modifier[key('matching-parent', ../Number)]/text()">
<xsl:value-of select="concat('STATUS', $incre+1)" />
</xsl:template>
</xsl:stylesheet>
However, my logic with the $incre fails, because it never increments, it always remains STATUS1.
Upvotes: 1
Views: 241
Reputation: 116959
first change all the nodes where
<name>
= SanJose and<status>
= 1, and then take the<Number>
from such cases and change it everywhere else where that<Number>
occurs
If I understand correctly, this could also be expressed as:
Number
;[Name='SanJose' and Status='1']
, then change the entire group.Looking at it this way, you could streamline the solution to:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="matching-parent" match="Parent2[Name='SanJose' and Status=1]" use="Number" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Modifier[key('matching-parent', ../Number)]/text()">
<xsl:value-of select="1"/>
</xsl:template>
</xsl:stylesheet>
Applied to the following test input:
<Parent1>
<Parent2>
<Number>111</Number>
<Name>Starter</Name>
<Status>2</Status>
<Modifier>0</Modifier>
</Parent2>
<Parent2>
<Number>111</Number>
<Name>SanJose</Name>
<Status>1</Status>
<Modifier>0</Modifier>
</Parent2>
<Parent2>
<Number>222</Number>
<Name>SanJose</Name>
<Status>2</Status>
<Modifier>0</Modifier>
</Parent2>
<Parent2>
<Number>111</Number>
<Name>Another 1</Name>
<Status>2</Status>
<Modifier>0</Modifier>
</Parent2>
<Parent2>
<Number>222</Number>
<Name>Another 2</Name>
<Status>1</Status>
<Modifier>0</Modifier>
</Parent2>
<Parent2>
<Number>111</Number>
<Name>SanJose</Name>
<Status>2</Status>
<Modifier>0</Modifier>
</Parent2>
</Parent1>
produces this result:
<?xml version="1.0" encoding="UTF-8"?>
<Parent1>
<Parent2>
<Number>111</Number>
<Name>Starter</Name>
<Status>2</Status>
<Modifier>1</Modifier>
</Parent2>
<Parent2>
<Number>111</Number>
<Name>SanJose</Name>
<Status>1</Status>
<Modifier>1</Modifier>
</Parent2>
<Parent2>
<Number>222</Number>
<Name>SanJose</Name>
<Status>2</Status>
<Modifier>0</Modifier>
</Parent2>
<Parent2>
<Number>111</Number>
<Name>Another 1</Name>
<Status>2</Status>
<Modifier>1</Modifier>
</Parent2>
<Parent2>
<Number>222</Number>
<Name>Another 2</Name>
<Status>1</Status>
<Modifier>0</Modifier>
</Parent2>
<Parent2>
<Number>111</Number>
<Name>SanJose</Name>
<Status>2</Status>
<Modifier>1</Modifier>
</Parent2>
</Parent1>
Note especially the last node in the example.
If I understand your new requirement correctly, you need to change this:
<xsl:template match="Modifier[key('matching-parent', ../Number)]/text()">
<xsl:value-of select="1"/>
</xsl:template>
to:
<xsl:template match="Modifier[key('matching-parent', ../Number)]">
<xsl:copy>
<xsl:value-of select="concat('STATUS', count(../preceding-sibling::Parent2[key('matching-parent', Number)]) + 1)"/>
</xsl:copy>
</xsl:template>
Upvotes: 1
Reputation: 7173
I came up with the following stylesheet from what I can understand with your question:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="SJ" match="Parent2[contains(Name, 'SanJose') and Status = 1]" use="Number"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Modifier">
<xsl:copy>
<xsl:choose>
<xsl:when test="contains(preceding-sibling::Name, 'SanJose')
and
preceding-sibling::Status = 1">
<xsl:text>1</xsl:text>
</xsl:when>
<xsl:when test="key('SJ', preceding-sibling::Number)">
<xsl:text>1</xsl:text>
</xsl:when>
<xsl:otherwise><xsl:value-of select="."/></xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
it produces:
<Parent1>
<Parent2>
<Number>"100"</Number>
<Name>"SanJose"</Name>
<Type>"SanJoseExtra"</Type>
<Adress>Avenue 54</Adress>
<Status>2</Status>
<TR5>1</TR5>
<TR10>0</TR10>
<Modifier>1</Modifier>
</Parent2>
<Parent2>
<Number>"100"</Number>
<Name>"SanTropez"</Name>
<Type>"SanTropezSmall"</Type>
<Adress>British Cal 3</Adress>
<Status>2</Status>
<TR5>1</TR5>
<TR10>1</TR10>
<Modifier>1</Modifier>
</Parent2>
<Parent2>
<Number>"101"</Number>
<Name>"SanJose"</Name>
<Type>"SanDiegoMedium"</Type>
<Adress>French Revolution n.n.</Adress>
<Status>2</Status>
<TR5>1</TR5>
<TR10>1</TR10>
<Modifier>0</Modifier>
</Parent2>
<Parent2>
<Number>"100"</Number>
<Name>"SanJose"</Name>
<Type>"SanJoseSmall"</Type>
<Adress>Avenue 54</Adress>
<Status>1</Status>
<TR5>1</TR5>
<TR10>0</TR10>
<Modifier>1</Modifier>
</Parent2>
</Parent1>
Upvotes: 1