Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

The xml::xslt documentation indicates I should use the format: <xsl:when test="path/@attr='value'"> to select an element by specifying an attribute value. When I use it, I get unexpected results. Am I using incorrect syntax?
foo.pl: #!/usr/bin/perl use strict; use warnings; use XML::XSLT qw( ); use Object::Destroyer qw( ); my $xslt = Object::Destroyer->new( XML::XSLT->new('foo.xslt', warnings => 1), 'dispose', ); $xslt->transform('foo.xml'); print $xslt->toString;
foo.xml:
<?xml version="1.0" encoding="utf-8"?> <PLMXML xmlns="http://www.plmxml.org/Schemas/PLMXMLSchema"> <Form id="id24" name="160D999998-98/01" accessRefs="#id3" subType="P +art Revision Master" subClass="Part Revision Master"> </Form> <Form id="id30" name="09A10-000019/A-AF Engineering Or" accessRefs=" +#id3" subType="AF Engineering Order E" subClass="AF Engineering Order + E"> </Form> <Form id="id33" name="09A10-000019/A-AF Design/Draftin" accessRefs=" +#id3" subType="AF Design/Drafting Request A" subClass="AF Design/Draf +ting Request A"> </Form> <Form id="id36" name="09A10-000019/A" accessRefs="#id3" subType="Eng +Change Revision Master" subClass="EngChange Revision Master"> </Form> </PLMXML>
foo.xslt:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Tr +ansform"> <xsl:template match="/"> <xsl:for-each select="/PLMXML/Form"> <xsl:if test="/PLMXML/Form[@id=id]"> <xsl:value-of select="@id"/> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet>
Returns:id24id30id33id36 Also Tried:
<xsl:for-each select="/PLMXML/Form"> <xsl:if test="/PLMXML/Form[@id=id*]"> <xsl:value-of select="@id"/> </xsl:if> </xsl:for-each>
Returns:id24id30id33id36 Also Tried:
<xsl:for-each select="/PLMXML/Form"> <xsl:if test="/PLMXML/Form[@id=id24]"> <xsl:value-of select="@id"/> </xsl:if> </xsl:for-each>
Returns:id24id30id33id36 Also Tried:
<xsl:for-each select="/PLMXML/Form"> <xsl:if test="/PLMXML/Form[@id=id2]"> <xsl:value-of select="@id"/> </xsl:if> </xsl:for-each>
Returns:id24id30id33id36 Also Tried:
<xsl:for-each select="/PLMXML/Form"> <xsl:if test="/PLMXML/Form[@id=]"> <xsl:value-of select="@id"/> </xsl:if> </xsl:for-each>
Returns:id24id30id33id36

Replies are listed 'Best First'.
Re: xml::xslt xpath bug?
by ikegami (Patriarch) on Jul 07, 2009 at 15:26 UTC

    What is the expected output? From your second attempt, I'm guessing you want all the nodes whose id attribute start with "id".

    The following would be what you want, but XML::XSLT doesn't recognize it:

    <xsl:if test="/PLMXML/Form[starts-with(@id, 'id')]">

    XML::XSLT doesn't recognize the following either:

    <xsl:if test="/PLMXML/Form[substr(@id, 1, 2)='id']">

    XML::XSLT uses its own bad XPath engine instead of a complete, tried and true engine. You should be looking for alternatives.

    Update: The above work if you remove the spaces.

    <xsl:if test="/PLMXML/Form[starts-with(@id,'id')]">
Re: xml::xslt xpath bug?
by ikegami (Patriarch) on Jul 07, 2009 at 15:30 UTC

    Don't forget to quote your values. Your code

    <xsl:if test="/PLMXML/Form[@id=id24]">

    should be

    <xsl:if test="/PLMXML/Form[@id='id24']">

    Unquoted would try to find a child element named id24. (Well, it's suppose to. I don't have much faith in XML::XSLT.)

    Both single and double quotes are equivalent in XPaths. Don't forget to appropriately escaped them according to the enclosing quotes.

    <xsl:if test="/PLMXML/Form[@id='id24']"> <xsl:if test='/PLMXML/Form[@id="id24"]'> <xsl:if test="/PLMXML/Form[@id=&quot;id24&quot;]"> <xsl:if test='/PLMXML/Form[@id=&apos;id24&apos;]'>
      Which Perl Module would you recommend I use to get this done? I tried each of the suggested forms and each returned an unexpected element.
      <xsl:for-each select='/PLMXML/Form[@id=&apos;id24&apos;]'> <xsl:value-of select="@id"/> </xsl:for-each> returns: id36 <xsl:for-each select="/PLMXML/Form[@id=&quot;id24&quot;]"> <xsl:value-of select="@id"/> </xsl:for-each> returns: id36 <xsl:for-each select='/PLMXML/Form[@id="id24"]'> <xsl:value-of select="@id"/> </xsl:for-each> returns: id36 <xsl:for-each select="/PLMXML/Form[@id='id24']"> <xsl:value-of select="@id"/> </xsl:for-each> returns: id36
        Sorry, I can't make a recommendation. I've never used XSLT.
Re: xml::xslt xpath bug?
by Anonymous Monk on Jul 07, 2009 at 14:41 UTC
    That code doesn't produce any output for me
      Did you try it with the exact value of one of the element's attributes (case # 3, I think)? BTW, thanks for commenting.
      <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Tr +ansform"> <xsl:template match="/"> <xsl:for-each select="/PLMXML/Form"> <xsl:if test="/PLMXML/Form[@id=id24]"> <xsl:value-of select="@id"/> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet>
        Yes, I used the download link.