Re: match if an attribute has a value, or is not available.

Discussion in 'XML' started by Dimitre Novatchev, Jul 5, 2003.

  1. > <xsl:template match="*[@xml:lang = 'ES' or not
    > attribute-available(@xml:lang)]" />
    > </xsl:stylesheet>
    >
    > I need the equivalent of the function attribute-available(). Other
    > permutations of this filter naturally result in no nodes in the output XML


    *[@xml:lang='ES' or not(@xml:lang)]


    or


    *[not(@xml:lang and @xml:lang != 'ES') ]




    =====
    Cheers,

    Dimitre Novatchev.
    http://fxsl.sourceforge.net/ -- the home of FXSL
    Dimitre Novatchev, Jul 5, 2003
    #1
    1. Advertising

  2. Dimitre Novatchev

    Phlip Guest

    > *[@xml:lang='ES' or not(@xml:lang)]

    > or


    > *[not(@xml:lang and @xml:lang != 'ES') ]


    Thanks, but (given 'xsltproc oneLang.xslt manyLang.xml'), the second returns
    only tags with no xml:lang at all, and the first returns no nodes
    whatsoever.

    (Using libxml 20507, libxslt 10030 and libexslt 720
    xsltproc was compiled against libxml 20507, libxslt 10030 and libexslt 720
    libxslt 10030 was compiled against libxml 20507
    libexslt 720 was compiled against libxml 20507)

    BTW I have solved my outer problem with this script:

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/|@*|node()">
    <xsl:copy>
    <xsl:apply-templates
    select="(@*|node())[descendant-or-self::*[lang($copy-lang)] or
    not(@xml:lang)]"/>
    </xsl:copy>
    </xsl:template>
    </xsl:stylesheet>

    But it's still not as minimal as I would have liked. One uses it like this:

    xsltproc --param copy-lang "'es'" oneLang.xslt manyLang.xml

    --
    Phlip
    http://www.c2.com/cgi/wiki?TestFirstUserInterfaces
    Phlip, Jul 5, 2003
    #2
    1. Advertising

  3. "Phlip" <> wrote in message
    news:be7526$...
    > > *[@xml:lang='ES' or not(@xml:lang)]

    >
    > > or

    >
    > > *[not(@xml:lang and @xml:lang != 'ES') ]

    >
    > Thanks, but (given 'xsltproc oneLang.xslt manyLang.xml'), the second

    returns
    > only tags with no xml:lang at all, and the first returns no nodes
    > whatsoever.


    I cannot reproduce this. With 8 different XSLT processors and with this
    transformation:

    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:eek:utput omit-xml-declaration="yes" indent="yes"/>

    <xsl:template match="/">
    /*/*[@xml:lang='ES' or not(@xml:lang)]
    <xsl:copy-of select="/*/*[@xml:lang='ES' or not(@xml:lang)]"/>

    /*/*[not(@xml:lang and @xml:lang != 'ES') ]
    <xsl:copy-of select="/*/*[not(@xml:lang and @xml:lang != 'ES') ]"/>

    </xsl:template>
    </xsl:stylesheet>


    when applied on your source.xml:

    <gloss>
    <note>has no language, so this remains</note>
    <verbiage xml:lang="EN">dog</verbiage>
    <verbiage xml:lang="ES">perro</verbiage>
    <verbiage xml:lang="PT">cao</verbiage>
    </gloss>

    The same (wanted) result is produced:


    /*/*[@xml:lang='ES' or not(@xml:lang)]
    <note>has no language, so this remains</note><verbiage
    xml:lang="ES">perro</verbiage>

    /*/*[not(@xml:lang and @xml:lang != 'ES') ]
    <note>has no language, so this remains</note>
    <verbiage xml:lang="ES">perro</verbiage>


    >
    > (Using libxml 20507, libxslt 10030 and libexslt 720
    > xsltproc was compiled against libxml 20507, libxslt 10030 and libexslt 720
    > libxslt 10030 was compiled against libxml 20507
    > libexslt 720 was compiled against libxml 20507)


    One of these 8 XSLT processors is xsltProc (libxml 20504, libxslt 10027.
    libexslt 718)

    >
    > BTW I have solved my outer problem with this script:
    >
    > <?xml version="1.0"?>
    > <xsl:stylesheet version="1.0"
    > xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    > <xsl:template match="/|@*|node()">
    > <xsl:copy>
    > <xsl:apply-templates
    > select="(@*|node())[descendant-or-self::*[lang($copy-lang)] or
    > not(@xml:lang)]"/>


    This is incorrect -- see below.


    > </xsl:copy>
    > </xsl:template>
    > </xsl:stylesheet>
    >
    > But it's still not as minimal as I would have liked. One uses it like

    this:
    >



    In your first message you said "The source has many languages,
    and the target only one."

    Your solution, when applied with $copy-lang set to "ES" on this source.xml:

    <gloss>
    <note lang="CH">
    This has a language different from ES
    and must not be copied!!!
    <subnote xml:lang="ES">perro</subnote>
    <subnote xml:lang="EN">dog</subnote>
    </note>
    <verbiage xml:lang="EN">dog</verbiage>
    <verbiage xml:lang="ES">perro</verbiage>
    <verbiage xml:lang="PT">cao</verbiage>
    </gloss>

    produces this result:

    <?xml version="1.0" encoding="UTF-16"?><gloss>
    <note lang="CH">
    This has a language different from ES
    and must not be copied!!!
    <subnote xml:lang="ES">perro</subnote>

    </note>

    <verbiage xml:lang="ES">perro</verbiage>

    </gloss>


    The "note" element is in the "CH" language, and the result is in two
    languages ("CH" and "ES"), not in one.



    =====
    Cheers,

    Dimitre Novatchev.
    http://fxsl.sourceforge.net/ -- the home of FXSL
    Dimitre Novatchev, Jul 5, 2003
    #3
  4. Dimitre Novatchev

    Marrow Guest

    Hi Phlip,

    I'm not sure if this will apply to the XML documents you are filtering - but
    be wary that the xml:lang also applies to descendants of the element on
    which it is declared where it is not overridden on those descendants.

    For example, the following XML...

    <?xml version="1.0"?>
    <gloss xml:lang="EN">
    <note>has no language - but is a descendant of one that does</note>
    <verbiage xml:lang="EN">dog</verbiage>
    <verbiage xml:lang="ES">perro</verbiage>
    <verbiage xml:lang="PT">cao</verbiage>
    </gloss>

    The language of the <note> element is now 'EN' because it desecends from
    <gloss> which is defined as 'EN'. So your current XSLT will copy that
    <note> even though it is not 'ES'. I think maybe a slight tweak to your
    XSLT should prevent that from happening...

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="copy-lang" select="'ES'"/>
    <xsl:template match="/|@*|node()">
    <xsl:copy>
    <xsl:apply-templates
    select="(@*|node())[descendant-or-self::*[lang($copy-lang)] or
    (not(@xml:lang) and lang($copy-lang))]"/>
    </xsl:copy>
    </xsl:template>
    </xsl:stylesheet>

    Cheers
    Marrow
    http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
    http://www.topxml.com/Xselerator

    "Phlip" <> wrote in message
    news:be7526$...
    > > *[@xml:lang='ES' or not(@xml:lang)]

    >
    > > or

    >
    > > *[not(@xml:lang and @xml:lang != 'ES') ]

    >
    > Thanks, but (given 'xsltproc oneLang.xslt manyLang.xml'), the second

    returns
    > only tags with no xml:lang at all, and the first returns no nodes
    > whatsoever.
    >
    > (Using libxml 20507, libxslt 10030 and libexslt 720
    > xsltproc was compiled against libxml 20507, libxslt 10030 and libexslt 720
    > libxslt 10030 was compiled against libxml 20507
    > libexslt 720 was compiled against libxml 20507)
    >
    > BTW I have solved my outer problem with this script:
    >
    > <?xml version="1.0"?>
    > <xsl:stylesheet version="1.0"
    > xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    > <xsl:template match="/|@*|node()">
    > <xsl:copy>
    > <xsl:apply-templates
    > select="(@*|node())[descendant-or-self::*[lang($copy-lang)] or
    > not(@xml:lang)]"/>
    > </xsl:copy>
    > </xsl:template>
    > </xsl:stylesheet>
    >
    > But it's still not as minimal as I would have liked. One uses it like

    this:
    >
    > xsltproc --param copy-lang "'es'" oneLang.xslt manyLang.xml
    >
    > --
    > Phlip
    > http://www.c2.com/cgi/wiki?TestFirstUserInterfaces
    >
    >
    Marrow, Jul 5, 2003
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Gerald Aichholzer
    Replies:
    5
    Views:
    43,128
    Gerald Aichholzer
    May 25, 2005
  2. Replies:
    1
    Views:
    4,236
    Joe Kesselman
    Aug 2, 2006
  3. Replies:
    8
    Views:
    513
  4. patrin
    Replies:
    5
    Views:
    889
    Dimitre Novatchev
    Sep 2, 2006
  5. johnny
    Replies:
    5
    Views:
    709
    johnny
    Dec 10, 2006
Loading...

Share This Page