Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   XML (http://www.velocityreviews.com/forums/f32-xml.html)
-   -   Stumped - Need XSLT Help (http://www.velocityreviews.com/forums/t370246-stumped-need-xslt-help.html)

J 09-12-2006 10:27 PM

Stumped - Need XSLT Help
 
I've spent most of the day on this, and I just can't seem to find a
solution, please help me! :)

I'm recieving XML that I can't modify that looks like:

<?xml version="1.0"?>
<Doc>
<Page>
<Item Value="A" Id="1" Count="1"/>
<Item Value="B" Id="2" Count="1"/>
<Item Value="C" Id="3" Count="1"/>
<Item Value="D" Id="1" Count="2"/>
<Item Value="E" Id="2" Count="2"/>
<Item Value="F" Id="3" Count="2"/>
<Item Value="G" Id="1" Count="3"/>
<Item Value="H" Id="2" Count="3"/>
<Item Value="I" Id="3" Count="3"/>
</Page>
</Doc>


And I need to transform it into:

<Doc>
<Page>
<Line>
<Tag1>A</Tag1>
<Tag2>B</Tag2>
<Tag3>C</Tag3>
</Line>
<Line>
<Tag1>D</Tag1>
<Tag2>E</Tag2>
<Tag3>F</Tag3>
</Line>
<Line>
<Tag1>G</Tag1>
<Tag2>H</Tag2>
<Tag3>I</Tag3>
</Line>
</Page>
</Doc>

But I can't seem to figure out how to create a new "Line" node based on
the count attribute.

Here is XSLT I have now:


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

<xsl:template match="Doc">
<Doc>
<xsl:apply-templates select="Page"/>
</Doc>
</xsl:template>

<xsl:template match="Page">
<Page>
<Line>
<xsl:for-each select="Item">

<xsl:if test="@Id='1'">
<Tag1><xsl:value-of select="@Value"/></Tag1>
</xsl:if>
<xsl:if test="@Id='2'">
<Tag2><xsl:value-of select="@Value"/></Tag2>
</xsl:if>
<xsl:if test="@Id='3'">
<Tag3><xsl:value-of select="@Value"/></Tag3>
</xsl:if>

</xsl:for-each>
</Line>
</Page>
</xsl:template>
</xsl:stylesheet>


Which only produces:

<Doc>
<Page>
<Line>
<Tag1>A</Tag1>
<Tag2>B</Tag2>
<Tag3>C</Tag3>
<Tag1>D</Tag1>
<Tag2>E</Tag2>
<Tag3>F</Tag3>
<Tag1>G</Tag1>
<Tag2>H</Tag2>
<Tag3>I</Tag3>
</Line>
</Page>
</Doc>


Any help at all is warmly welcomed!


Dimitre Novatchev 09-13-2006 01:41 AM

Re: Stumped - Need XSLT Help
 
Read about and use the XPath "mod" operator


Cheers,
Dimitre Novatchev


"J" <darkfalz@mindspring.com> wrote in message
news:1158100067.382822.288280@i3g2000cwc.googlegro ups.com...
> I've spent most of the day on this, and I just can't seem to find a
> solution, please help me! :)
>
> I'm recieving XML that I can't modify that looks like:
>
> <?xml version="1.0"?>
> <Doc>
> <Page>
> <Item Value="A" Id="1" Count="1"/>
> <Item Value="B" Id="2" Count="1"/>
> <Item Value="C" Id="3" Count="1"/>
> <Item Value="D" Id="1" Count="2"/>
> <Item Value="E" Id="2" Count="2"/>
> <Item Value="F" Id="3" Count="2"/>
> <Item Value="G" Id="1" Count="3"/>
> <Item Value="H" Id="2" Count="3"/>
> <Item Value="I" Id="3" Count="3"/>
> </Page>
> </Doc>
>
>
> And I need to transform it into:
>
> <Doc>
> <Page>
> <Line>
> <Tag1>A</Tag1>
> <Tag2>B</Tag2>
> <Tag3>C</Tag3>
> </Line>
> <Line>
> <Tag1>D</Tag1>
> <Tag2>E</Tag2>
> <Tag3>F</Tag3>
> </Line>
> <Line>
> <Tag1>G</Tag1>
> <Tag2>H</Tag2>
> <Tag3>I</Tag3>
> </Line>
> </Page>
> </Doc>
>
> But I can't seem to figure out how to create a new "Line" node based on
> the count attribute.
>
> Here is XSLT I have now:
>
>
> <?xml version="1.0" encoding="UTF-8" ?>
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
> <xsl:output method="xml" />
>
> <xsl:template match="Doc">
> <Doc>
> <xsl:apply-templates select="Page"/>
> </Doc>
> </xsl:template>
>
> <xsl:template match="Page">
> <Page>
> <Line>
> <xsl:for-each select="Item">
>
> <xsl:if test="@Id='1'">
> <Tag1><xsl:value-of select="@Value"/></Tag1>
> </xsl:if>
> <xsl:if test="@Id='2'">
> <Tag2><xsl:value-of select="@Value"/></Tag2>
> </xsl:if>
> <xsl:if test="@Id='3'">
> <Tag3><xsl:value-of select="@Value"/></Tag3>
> </xsl:if>
>
> </xsl:for-each>
> </Line>
> </Page>
> </xsl:template>
> </xsl:stylesheet>
>
>
> Which only produces:
>
> <Doc>
> <Page>
> <Line>
> <Tag1>A</Tag1>
> <Tag2>B</Tag2>
> <Tag3>C</Tag3>
> <Tag1>D</Tag1>
> <Tag2>E</Tag2>
> <Tag3>F</Tag3>
> <Tag1>G</Tag1>
> <Tag2>H</Tag2>
> <Tag3>I</Tag3>
> </Line>
> </Page>
> </Doc>
>
>
> Any help at all is warmly welcomed!
>




George Bina 09-13-2006 07:25 AM

Re: Stumped - Need XSLT Help
 
Hi,

You can match on the first Item, then create a Line element and put
inside the output for all the items with the same Count value and then
apply match on the Item with the next count value, create again a Line
element and place inside the output for the Item elements with the same
Count value and so on, see

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="/">
<Doc><Page><xsl:apply-templates
select="Doc/Page/Item[1]"/></Page></Doc>
</xsl:template>
<xsl:template match="Item">
<Line>
<xsl:apply-templates select="../Item[@Count=current()/@Count]"
mode="print"/>
</Line>
<xsl:apply-templates
select="../Item[@Count=1+current()/@Count][1]"/>
</xsl:template>
<xsl:template match="Item" mode="print">
<xsl:element name="Tag{@Id}"><xsl:value-of
select="@Value"/></xsl:element>
</xsl:template>
</xsl:stylesheet>

Best Regards,
George
---------------------------------------------------------------------
George Cristian Bina
<oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
http://www.oxygenxml.com



J wrote:
> I've spent most of the day on this, and I just can't seem to find a
> solution, please help me! :)
>
> I'm recieving XML that I can't modify that looks like:
>
> <?xml version="1.0"?>
> <Doc>
> <Page>
> <Item Value="A" Id="1" Count="1"/>
> <Item Value="B" Id="2" Count="1"/>
> <Item Value="C" Id="3" Count="1"/>
> <Item Value="D" Id="1" Count="2"/>
> <Item Value="E" Id="2" Count="2"/>
> <Item Value="F" Id="3" Count="2"/>
> <Item Value="G" Id="1" Count="3"/>
> <Item Value="H" Id="2" Count="3"/>
> <Item Value="I" Id="3" Count="3"/>
> </Page>
> </Doc>
>
>
> And I need to transform it into:
>
> <Doc>
> <Page>
> <Line>
> <Tag1>A</Tag1>
> <Tag2>B</Tag2>
> <Tag3>C</Tag3>
> </Line>
> <Line>
> <Tag1>D</Tag1>
> <Tag2>E</Tag2>
> <Tag3>F</Tag3>
> </Line>
> <Line>
> <Tag1>G</Tag1>
> <Tag2>H</Tag2>
> <Tag3>I</Tag3>
> </Line>
> </Page>
> </Doc>
>
> But I can't seem to figure out how to create a new "Line" node based on
> the count attribute.
>
> Here is XSLT I have now:
>
>
> <?xml version="1.0" encoding="UTF-8" ?>
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
> <xsl:output method="xml" />
>
> <xsl:template match="Doc">
> <Doc>
> <xsl:apply-templates select="Page"/>
> </Doc>
> </xsl:template>
>
> <xsl:template match="Page">
> <Page>
> <Line>
> <xsl:for-each select="Item">
>
> <xsl:if test="@Id='1'">
> <Tag1><xsl:value-of select="@Value"/></Tag1>
> </xsl:if>
> <xsl:if test="@Id='2'">
> <Tag2><xsl:value-of select="@Value"/></Tag2>
> </xsl:if>
> <xsl:if test="@Id='3'">
> <Tag3><xsl:value-of select="@Value"/></Tag3>
> </xsl:if>
>
> </xsl:for-each>
> </Line>
> </Page>
> </xsl:template>
> </xsl:stylesheet>
>
>
> Which only produces:
>
> <Doc>
> <Page>
> <Line>
> <Tag1>A</Tag1>
> <Tag2>B</Tag2>
> <Tag3>C</Tag3>
> <Tag1>D</Tag1>
> <Tag2>E</Tag2>
> <Tag3>F</Tag3>
> <Tag1>G</Tag1>
> <Tag2>H</Tag2>
> <Tag3>I</Tag3>
> </Line>
> </Page>
> </Doc>
>
>
> Any help at all is warmly welcomed!



p.lepin@ctncorp.com 09-13-2006 10:40 AM

Re: Stumped - Need XSLT Help
 

J wrote:
> I've spent most of the day on this, and I just can't seem
> to find a solution, please help me! :)
>
> I'm recieving XML that I can't modify that looks like:
>
> <?xml version="1.0"?>
> <Doc>
> <Page>
> <Item Value="A" Id="1" Count="1"/>
> <Item Value="B" Id="2" Count="1"/>
> <Item Value="C" Id="3" Count="1"/>
> <Item Value="D" Id="1" Count="2"/>
> <Item Value="E" Id="2" Count="2"/>
> <Item Value="F" Id="3" Count="2"/>
> <Item Value="G" Id="1" Count="3"/>
> <Item Value="H" Id="2" Count="3"/>
> <Item Value="I" Id="3" Count="3"/>
> </Page>
> </Doc>
>
> And I need to transform it into:


[<Item>s grouped into <Line>s by Count attribute]

I'm not an XSLT expert, just toying with it in my spare
time, so there are probably much better solutions to your
problem; nevertheless, the following XSLT seems to produce
the results you need:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output
method="xml"
version="1.0"
encoding="UTF-8"/>
<xsl:template match="/Doc">
<Doc>
<xsl:apply-templates select="./Page"/>
</Doc>
</xsl:template>
<xsl:template match="Page">
<Page>
<xsl:apply-templates select="./Item">
<xsl:with-param name="l">1</xsl:with-param>
</xsl:apply-templates>
</Page>
</xsl:template>
<xsl:template match="Item">
<xsl:param name="l"/>
<xsl:choose>
<xsl:when test="$l='0'">
<xsl:choose>
<xsl:when test="@Id='1'">
<Tag1><xsl:value-of select="@Value"/></Tag1>
</xsl:when>
<xsl:when test="@Id='2'">
<Tag2><xsl:value-of select="@Value"/></Tag2>
</xsl:when>
<xsl:when test="@Id='3'">
<Tag3><xsl:value-of select="@Value"/></Tag3>
</xsl:when>
</xsl:choose>
</xsl:when>
<xsl:when test="$l!='0'">
<xsl:if
test="
starts-with(
generate-id(//Item[@Count=current()/@Count]),
generate-id(.))">
<Line>
<xsl:apply-templates
select="../Item[@Count=current()/@Count]">
<xsl:with-param name="l">0</xsl:with-param>
</xsl:apply-templates>
</Line>
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

--
Pavel Lepin


J 09-13-2006 01:19 PM

Re: Stumped - Need XSLT Help
 
Thanks for the responses all.

I stayed up late and found a way to do it with a grouping key.


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

<xsl:key name="line-by-count" match="Item" use="@Count"/>

<xsl:template match="Doc">
<Doc>
<xsl:apply-templates select="Page"/>
</Doc>
</xsl:template>


<xsl:template match="Page">
<Page>
<xsl:for-each
select="Item[count(.|key('line-by-count',@Count)[1])=1]">
<Line>
<xsl:for-each select="key('line-by-count',@Count)">
<xsl:if test="@Id='1'">
<Tag1><xsl:value-of select="@Value"/></Tag1>
</xsl:if>
<xsl:if test="@Id='2'">
<Tag2><xsl:value-of select="@Value"/></Tag2>
</xsl:if>
<xsl:if test="@Id='3'">
<Tag3><xsl:value-of select="@Value"/></Tag3>
</xsl:if>
</xsl:for-each>
</Line>
</xsl:for-each>
</Page>
</xsl:template>
</xsl:stylesheet>



All times are GMT. The time now is 04:48 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.