Forum Moderators: open

Message Too Old, No Replies

XSL filtering

         

crazy_horse

8:33 am on Mar 30, 2008 (gmt 0)

10+ Year Member



Hi,

I'm new to XSL and I need some help with removing the attribute "pagecount" and copy the rest of the tags and attributes. How do I do that with XSL?

<Contents>
<Content>
<Section seqno="01" />
<Page seqno="3637" pagecount="1" />
<PageSize unit="" width="" height="14.36" />
<PagePosition unit="" top="" left="" />
<Area unit="cm2">360.63</Area>
<Headline>Something</Headline>
<Byline />
<Introduction />
<Body />
<Pictures>
<captions />
</Pictures>
</Content>
</Contents>


The final result should be like this:

<Contents>
<Content>
<Section seqno="01" />
<Page seqno="3637" />
<PageSize unit="" width="" height="14.36" />
<PagePosition unit="" top="" left="" />
<Area unit="cm2">360.63</Area>
<Headline>Something</Headline>
<Byline />
<Introduction />
<Body />
<Pictures>
<captions />
</Pictures>
</Content>
</Contents>

Thanks

cmarshall

11:08 pm on Apr 1, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Huh. I never got a notification of this post. I just re-upped on WebmasterWorld (by the way, welcome to WebmasterWorld), so maybe it reset my watchlist.

In any case, there are a couple of ways in which you could do it. You can do it exclusively (everything but <pagecount>) or inclusively (specify exactly which elements you'll copy, and format each one).

I need to break out my "XSLT brain." I've been off in PHP and C++ land, which is way different from XSLT.

I know that you will need to have a template that might look like this:


<xsl:template match="Page">
<xsl:element name="Page">
<xsl:if test="@seqno">
<xsl:attribute name="seqno">
<xsl:value-of select="@seqno"/>
</xsl:attribute>
</xsl:if>
</xsl:element>
</xsl:template>

But I don't want to give you more advice than that, simply because it would end up looking like procedural code, which is improper for XSLT.

httpwebwitch

8:02 pm on Apr 2, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



here it is:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@* ¦ node()">
<xsl:choose>
<xsl:when test="@pagecount">
<xsl:copy>
<xsl:apply-templates select="@seqno ¦ node()"/>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@* ¦ node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

It's an adaptation of the classic "transparent XSLT" which returns the original XML:


<xsl:template match="@* ¦ node()">
<xsl:copy>
<xsl:apply-templates select="@* ¦ node()"/>
</xsl:copy>
</xsl:template>

In my adaptation, I choose if the current node contains the offensive attribute "pagesize". If it does, I apply a template allowing only child elements and approved attributes (in this case, only @seqno). Otherwise I apply a template which allows any child element or attribute.

Beware cutting and pasting the code-- this forum turns pipe "or" characters into "¦"

cmarshall

8:26 pm on Apr 2, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



What he said.

When he's not shoving Mentos up his nose, httpwebwitch is mastering XML. Darn good resource.

coopster

9:02 pm on Apr 2, 2008 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



LOL!
However, I believe that was his brother ...

httpwebwitch

2:03 am on Apr 3, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Nasal mentos + Coke experiments? I'd never do anything that silly. um, yeah, it was my ... brother. My brother, the trepanning victim who looks a lot like me but not quite as handsome.

my wife was out of town when that was filmed. she swore that if I ended up in the hospital with fragments of mint lodged deep in my sinuses, she would be too embarassed to visit me in the ICU

crazy_horse

6:33 am on Apr 4, 2008 (gmt 0)

10+ Year Member



Thank you very much for your suggestions but I still can't get it to work. I'm trying to do this change in a xsl that look like this in the end:

<xsl:template match="MetaXml">
<PressItem>
<xsl:attribute name="id">
<xsl:value-of select="Id" />
</xsl:attribute>
<xsl:if test="OriginalMetaXml/PressItem">
<xsl:attribute name="type">
<xsl:value-of select="OriginalMetaXml/PressItem/@type"/>
</xsl:attribute>
<xsl:copy-of select="Copyright"/>
<xsl:apply-templates select="OriginalMetaXml/PressItem" />
</xsl:if>
</PressItem>
</xsl:template>
<xsl:template match="OriginalMetaXml/PressItem">
<xsl:copy-of select="* [not(self::ArticleIdentifier ¦ self::ContentFiles ¦ self::FirstValidDateTime ¦ self::LastValidDateTime ¦ self::PostProcessedBy)]"/>
</xsl:template>

It's filtering some other tags that I had not included in my exampel. If I don't add self::Contents to line at the end, everything in Contents (including pagecount) are copied. I guess I should use self::Contents and include httpwebwitch solution somehow but I can't figure out how. Anyone?

httpwebwitch

1:14 pm on Apr 4, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Inside the template matching "OriginalMetaXml/PressItem" - that's where you want the filtered version of the original XML, right? So first: create a new template that does just that, probably a variation of the transparent XSLT in my example above. Once you have a template that does what you need, "call" it from within the "OriginalMetaXml/PressItem" template.

Say, crazy_horse, what tool are you using to test your XSLT? Do you have a good debugger that lets you edit XSLT and see the transformed output right away?

And... welcome to WebmasterWorld!

crazy_horse

2:00 pm on Apr 4, 2008 (gmt 0)

10+ Year Member



Thank you httpwebwitch. Yes, thats were I want the filtered version. I don't have a tool for testing, I just change the xsl on the test server and run a test application that shows the final result. A debugger sounds nice.

This is how it looks right now:

...
<xsl:template match="MetaXml">
<PressItem>
<xsl:attribute name="id">
<xsl:value-of select="Id" />
</xsl:attribute>

<xsl:if test="OriginalMetaXml/PressItem">
<xsl:attribute name="type">
<xsl:value-of select="OriginalMetaXml/PressItem/@type"/>
</xsl:attribute>
<xsl:copy-of select="Copyright"/>
<xsl:apply-templates select="OriginalMetaXml/PressItem" />
</xsl:if>
</PressItem>
</xsl:template>

<xsl:template match="OriginalMetaXml/PressItem">
<xsl:copy-of select="* [not(self::Contents ¦ self::ArticleIdentifier ¦ self::ContentFiles ¦ self::FirstValidDateTime ¦ self::LastValidDateTime ¦ self::PostProcessedBy)]"/>
<xsl:apply-templates select="Contents/Content" />
</xsl:template>

<xsl:template match="Contents/Content">
<xsl:choose>
<xsl:when test="@pagecount">
<xsl:copy>
<xsl:apply-templates select="@seqno ¦ node()"/>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@* ¦ node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

I have created the template Contents/Content and call it from the template OriginalMetaXml/PressItem.

httpwebwitch

2:23 pm on Apr 4, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I don't have a tool for testing

Go grab a trial version of <oXygen/>. It will add many hours of enjoyment to your life - because those will be hours you're not spending debugging XSLT!

I am not affiliated with <oXygen/> in any way; this is an unsolicited endorsement

cheers
hww

httpwebwitch

2:24 pm on Apr 4, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



oh, btw the link for that software is
www
dot
oxygenxml
dot
com

cmarshall

2:25 pm on Apr 4, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'll second httpwebwitch's endorsement.

I couldn't imagine trying to debug this stuff without it.

crazy_horse

3:52 pm on Apr 4, 2008 (gmt 0)

10+ Year Member



Great, I will try that :)