Go Back   Velocity Reviews > Newsgroups > XML
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

Reply

XML - Stumped - Need XSLT Help

 
Thread Tools Search this Thread
Old 09-12-2006, 11:27 PM   #1
Default 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"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xslutput 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!



J
  Reply With Quote
Old 09-13-2006, 02:41 AM   #2
Dimitre Novatchev
 
Posts: n/a
Default Re: Stumped - Need XSLT Help

Read about and use the XPath "mod" operator


Cheers,
Dimitre Novatchev


"J" <> wrote in message
news: 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"
> xmlnssl="http://www.w3.org/1999/XSL/Transform">
> <xslutput 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!
>



  Reply With Quote
Old 09-13-2006, 08:25 AM   #3
George Bina
 
Posts: n/a
Default 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"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xslutput 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"
> xmlnssl="http://www.w3.org/1999/XSL/Transform">
> <xslutput 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!


  Reply With Quote
Old 09-13-2006, 11:40 AM   #4
p.lepin@ctncorp.com
 
Posts: n/a
Default 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
xmlnssl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xslutput
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">
<xslaram 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

  Reply With Quote
Old 09-13-2006, 02:19 PM   #5
J
 
Posts: n/a
Default 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"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xslutput 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>

  Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump