Re: spot/remove repeated elements in XML documet
Manuel Souto Pico <[email protected]>
| Newsgroups | gmane.comp.lang.perl.xml |
|---|---|
| Message-ID | <[email protected]> |
Hi again, Michael,
Thanks for your reply. Indeed, XSLT seems like the easiest option to do
this processing. However, I don't have enough knowledge about XLST in
order to understand well some things in your proposal, I might need to
study a bit...
I will ask about one only: <xsl:variable name="unlikely"
select="'||--||'"/>. I understand this is what might be between elements
Eng and Spa, but I don't understand the '||--||'. Could you explain?
Anyway, I tried to use your template to process my example (which is a
simplified version of the document that I need to process) but I get
some errors (in Oxygen). Using XSLT 1.0, the line <xsl:key name="dupl"
match="entry" use="concat( Eng, $unlikely, Spa)"/> gives the error: "The
expressions in xsl:key may not contain references to variables". Using
2.0, it is the line generate-id( key( 'dupl', $lookup-key)[ 1 ] )"> that
gives the same error.
However, using the Muenchian grouping thing, I've done some tests on my
side and I've mananged to come up with this (please tell me whether it
should be more appropriate to post this in the list for XSL):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="eng-by-content" match="entry/Eng" use="."/>
<xsl:key name="spa-by-content" match="entry/Spa" use="."/>
<xsl:template match="/dictionary">
<dictionary>
<xsl:for-each select="entry/Eng">
<xsl:if test="generate-id(.) =
generate-id(key('eng-by-content', .)[1]) ">
<text>
<eng>
<xsl:value-of select="."/>
</eng>
<spa>
<xsl:value-of select="../Spa/."/>
</spa>
</text>
</xsl:if>
</xsl:for-each>
</dictionary>
</xsl:template>
</xsl:stylesheet>
for the data (note the added root element):
<?xml version="1.0" encoding="UTF-8"?>
<dictionary>
<entry id="1">
<Eng>house</Eng>
<Spa>casa</Spa>
</entry>
<entry id="2">
<Eng>shoe</Eng>
<Spa>zapato</Spa>
</entry>
<entry id="3">
<Eng>house</Eng>
<Spa>casa</Spa>
</entry>
<entry id="4">
<Eng>house</Eng>
<Spa>morada</Spa>
</entry>
</dictionary>
This XSL sheet allows me to output only the entries with no duplicate
English term (say, 1 and 2), and that's already something. I've tried
applying your concatenation syntax but I can't manage to use both
languages as criteria (to output entries 1, 2 and *4* but not 3). That's
what I have so far.
Thanks a lot for your help!
Manuel
Michael Ludwig escribió:
> Manuel Souto Pico schrieb:
>
>
>> <entry ="10">
>> <Eng>house</Eng>
>> <Spa>casa</Spa>
>> </entry>
>>
>
> The <entry> element, of course, is not valid.
>
>
>> <entry ="12">
>> <Eng>house</Eng>
>> <Spa>casa</Spa>
>> </entry>
>>
>
>
>> where as you can see, entries 10 and 12 have identical contents.
>>
>> My question is: Is there any easy way to spot and/or remove repeated
>> elements? I suppose it could be done with XSL or a perl module for
>> XML...
>>
>
> It is not complicated. First, define identity. In your case, that may be
> the concatenation of <Eng> and <Spa>. (It might also be something else.)
>
> Then, in XSLT 2.0 it would be really easy. But with Perl, you only have
> XSLT 1.0 at your disposal.
>
> Here's an XSLT 1.0 solution. The algorithm is simple: Find duplicates
> and eliminate all but the first one. The implementation may not be
> obvious at first sight, but it is not difficult. Do some googling for
> "Muenchian Grouping".
>
> Michael Ludwig
>
> <?xml version="1.0" encoding="ISO-8859-1"?>
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
>
> <xsl:variable name="unlikely" select="'||--||'"/>
> <xsl:key name="dupl" match="entry" use="concat( Eng, $unlikely, Spa)"/>
>
> <xsl:template match="document">
> <xsl:apply-templates select="entry"/>
> </xsl:template>
>
> <xsl:template match="entry">
> <xsl:variable name="lookup-key" select="concat(Eng, $unlikely, Spa)"/>
> <xsl:if test="
> generate-id() =
> generate-id( key( 'dupl', $lookup-key)[ 1 ] )">
> <xsl:copy>
> <xsl:apply-templates select="@*|node()"/>
> </xsl:copy>
> </xsl:if>
> </xsl:template>
>
> <xsl:template match="@*|node()">
> <xsl:copy>
> <xsl:apply-templates select="@*|node()"/>
> </xsl:copy>
> </xsl:template>
>
> </xsl:stylesheet>
> _______________________________________________
> Perl-XML mailing list
> [email protected]
> To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
>
>
>
_______________________________________________
Perl-XML mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs