Search

My apologies for being an XSLT n00b, but I can’t figure this one out.

I’ve added a Twitter feed as a dynamic data source, with output similar to this:

http://twitter.com/statuses/user_timeline/ev.xml

That’s a lot of data, and I’d like to whittle it down to this:

<statuses>
    <status>
        <created_at />
        <text />
    </status>
</statuses>

My best bet was to add this under “Included Elements”:

/statuses/status/created_at/ancestor-or-self::* | //text

I’ve tested that expression in FireXPath where it works as expected, but Symphony spits out the whole feed. Is it perhaps not possible to use the “ancestor-or-self” axis when selected which elements to include, or am I missing something?

If there is a better way to select the and elements including their parent elements, I’d settle for that too :)

Thanks for any help!

Ergh… I should’ve read your question properly:

/statuses/status/*[name() = 'text' or name() = 'created_at']

Thanks, @phoque. Although that does the same as:

//created_at | //text

…which gets me those two elements, but not their ancestral <statuses> and <status>. How do I go about including them?

My first guess would be

/statuses/status/*[name() = 'text' or name() = 'created_at']/ancestor-or-self::*

I agree, that makes sense, but it returns the whole feed, and I can’t figure out why.

I’ve been playing around with it a bit and can’t make any sense of it… I am pretty sure my code above should work as we both expect it to do.

It looks like ancestor-of-self is returning a nodeset consisting of… well, all the ancestors.

But because the Dynamic XML DS creates a XSLT stylesheet including your expression on the fly with your expression wrapped in <xsl:copy-of /> it kind of makes sense that it’s returning everything as one could understand

<copy-of select="/statuses/status/*[name() = 'text' or name() = 'created_at']/ancestor-or-self::*" />

as being the equivalent to

<copy-of select="statuses|statuses/status|statuses/status/text|statuses/status/created_at" />

wich in turn is equivalent to simply

<copy-of select="statuses" />

Ah, that makes sense. Thanks for the clarification!

So, is there no way to select only <created_at>, <text> and their ancestors, ignoring all their siblings?

And is there even any performance gain from this exercise? It seems to make sense to whittle down the XML to only the nodes I will actually be using, but if there aren’t any performance gains, then it doesn’t matter much. I haven’t quite wrapped my head around Symphony’s internals yet :)

Wait, I think I found a workaround for this problem. Instead of using:

http://twitter.com/statuses/user_timeline/{user_name}.xml

I will just pull in the regular Atom feed:

http://twitter.com/statuses/user_timeline/{user_id}.rss

…which has a lot less data, but includes the elements that I need. I’m still curious how to ignore unnecessary siblings in the XPath declaration, though, so if anyone has any idea it’ll be much appreciated.

which has a lot less data, but includes the elements that I need. I’m still curious how to ignore unnecessary siblings in the XPath declaration, though, so if anyone has any idea it’ll be much appreciated.

I’m also curious how to do this. I have several feeds that I need to trim down.

I was thinking about this a lot last night, and I’m very far from being any type of xpath expert, but I really can’t think of any way to do this with one line of xpath.

It’s a shame that we can’t use a textarea to build an xml node-set using xsl, like you can with a variable in xslt, like

<statuses>
    <xsl:attribute name="type"><xsl:value-of select="/statuses/@type" /></xsl:attribute>
    <xsl:for-each select="/statuses/status">
        <xsl:copy-of select="created_at/text()" />
        <xsl:copy-of select="text/text()" />
    </xsl:for-each>
</statuses>

Basically transforming the input xml to how you want it. That would be so sweet…

And do what you want too…

EDIT: I’m actually putting this forward as a suggestion, but I may try and make a custom dynamic datasource type to do this…

Ah yes, excellent point, @designermonkey. That would indeed be a neat feature.

I’m very new to XPath/XSLT, but they seem like such powerful languages that I assumed pretty much everything was possible, but in this specific case I guess not.

I can of course easily extract only the <created_at> and <text> nodes, but if I lose their ancestors, I can’t subsequently do a <xsl:template match="status"> to process each set in turn, since the structure is lost. But yes, if it was possible to construct the nodeset via XSL rather than just XPath, that structure could be reconstructed.

I’ve been looking over the code that evaluates the Xpath expression in symphony/lib/toolkit/data-sources/datasource.dynamic_xml.php. Unfortunately, it isn’t part of a class that’s being extended (in the object oriented programming model sense) by your “DS instance”.

It would be a neat thing if it were because then your instance could overload that function with any custom XSLT (and not just the Xpath-string) you like.

Shame. May be possible in 3, not looked too much into it yet…

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details