Subject: [xsl] Re: [XSL-List: The Open Forum on XSL] Digest for 2017-08-30 From: "Imsieke, Gerrit, le-tex gerrit.imsieke@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Thu, 31 Aug 2017 12:31:24 -0000 |
below code i have modified but not working:
|<xsl:stylesheetversion="2.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:outputomit-xml-declaration="yes"indent="yes"/><xsl:strip-spaceelements="*"/><xsl:paramname="XMLMerge2"select="document('input2.xml')"/><xsl:keyname="kBymail"match="clientname"use="Email"/><xsl:templatematch="ClientInfo"><ClientInfo><xsl:for-eachselect="clientname"><xsl:variablename="Email_from_merge1"select="Id"/><xsl:choose><xsl:whentest="$XMLMerge2 = ''"><xsl:copy><xsl:copy-ofselect="node() | @*"/></xsl:copy></xsl:when><xsl:whentest="exists($XMLMerge2/ClientInfo/clientdata[name = $Email_from_merge1])"><xsl:copy><xsl:copy-ofselect="node() | @*"/></xsl:copy></xsl:when></xsl:choose></xsl:for-each></objects></xsl:template><xsl:templatematch="Contact[Email = following-sibling::Contact/Email]"/>|
On Thu, Aug 31, 2017 at 2:52 PM, XSL-List: The Open Forum on XSL <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx <mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>> wrote:
This message contains the recent posts to the XSL-List: The Open Forum on XSL mailing list managed by Mulberry Technologies, Inc. (http://lists.mulberrytech.com).
---------- Forwarded message ---------- From:B "Michael MC<ller-Hillebrand" <mmh@xxxxxxxxx <mailto:mmh@xxxxxxxxx>> To:B "xsl-list@xxxxxxxxxxxxxxxxxxxxxx <mailto:xsl-list@xxxxxxxxxxxxxxxxxxxxxx>" <XSL-List@xxxxxxxxxxxxxxxxxxxxxx <mailto:XSL-List@xxxxxxxxxxxxxxxxxxxxxx>> Cc: Bcc: Date:B Wed, 30 Aug 2017 20:48:55 +0200 Subject:B Can I use xsl:key to select elements up to certain ancestor Hi all,
I had an embarrassing moment today, when I found that the source of a severe performance problem was sitting in front of the screen.
Using XSLT 2.0 I am transforming elements and at many points I have to look up the ancestor axis, but only up to an element with an attribute "id". Basically I have a deeply nested structure of topics and I want to analyze ancestors inside the current topic.
The nearest topic is easy to find:
<xsl:variable name="topic" select="ancestor-or-self::*[@id][1]" as="element()"/>
And then I was doing the following to find all ancestors that share the same "topic ancestor":
<xsl:variable name="ancestors-in-topic" B select="ancestor-or-self::*[ancestor-or-self::* = $topic]" as="element()*"/>
This did not what I expected and also wasted a lot of resources because the predicate was true for all or most elements. After some testing I went with this:
<xsl:variable name="ancestors-in-topic" B select="ancestor-or-self::*[ancestor-or-self::*/generate-id() = generate-id($topic)]" as="element()*"/>
Since that calculation is done very often I am wondering if xsl:key could be used to speed things up?
Any pointers are very welcome, as always, thanks,
- Michael
PS: My sample XML and XSLT below.
<?xml version="1.0" encoding="UTF-8"?> <bars id="x0"> B <bar id="x1"> B B <bar id="x11"> B B B <bar id="x12"> B B B B <div> B B B B B <bar id="x13"> B B B B B B <div> B B B B B B B <p/> B B B B B B </div> B B B B B </bar> B B B B </div> B B B </bar> B B </bar> B </bar> </bars>
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform <http://www.w3.org/1999/XSL/Transform>" xmlns:xs="http://www.w3.org/2001/XMLSchema <http://www.w3.org/2001/XMLSchema>" version="2.0"> B <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/> B <xsl:strip-space elements="*"/>
B <xsl:template match="p"> B B <xsl:variable name="topic" select="ancestor-or-self::*[@id][1]" as="element()"/> B B <xsl:variable name="ancestors-in-topic" select="ancestor-or-self::*[ancestor-or-self::*/generate-id() = generate-id($topic)]" as="element()*"/> B B <xsl:copy> B B B <xsl:attribute name="topic" select="$topic/@id"/> B B B <xsl:text>Ancestors: </xsl:text> B B B B <xsl:sequence select="$ancestors-in-topic/name()"/> B B </xsl:copy> B </xsl:template>
B <xsl:template match="* | @*"> B B <xsl:copy> B B B <xsl:apply-templates select="@*, node()"/> B B </xsl:copy> B </xsl:template> </xsl:stylesheet>
Expected output for <p>: <p topic="x13">Ancestors: bar div p</p>
---------- Forwarded message ---------- From:B David Carlisle <d.p.carlisle@xxxxxxxxx <mailto:d.p.carlisle@xxxxxxxxx>> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx <mailto:xsl-list@xxxxxxxxxxxxxxxxxxxxxx> Cc: Bcc: Date:B Wed, 30 Aug 2017 20:08:05 +0100 Subject:B Re: [xsl] Can I use xsl:key to select elements up to certain ancestor You seem to be listing ancestor-or-self rather than ancestor, I think you only need to go up the ancestor axis once in each case, something like
<xsl:stylesheet version="2.0" B B B B xmlns:xsl="http://www.w3.org/1999/XSL/Transform <http://www.w3.org/1999/XSL/Transform>">
B <xsl:template match="/"> B <xsl:apply-templates select="//p"/><!-- just for testing--> B </xsl:template>
B <xsl:template match="*"> B <xsl:copy> B B <xsl:apply-templates select="." mode="a"/> B </xsl:copy> B </xsl:template>
B <xsl:template match="*" mode="a"> B <xsl:param name="trail" select="()"/> B <xsl:apply-templates select="parent::*" mode="a"> B B <xsl:with-param name="trail" select="name(),$trail"/> B </xsl:apply-templates> B </xsl:template>
B <xsl:template match="*[@id]" mode="a"> B <xsl:param name="trail" select="()"/> B B <xsl:copy-of select="@id,'Ancestors:', name(), $trail"/> B </xsl:template>
</xsl:stylesheet>
which makes
<p id="x13">Ancestors: bar div p</p>
On 30 August 2017 at 19:49, Michael MC<ller-Hillebrand mmh@xxxxxxxxx
<mailto:mmh@xxxxxxxxx>
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx
<mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>> wrote:
> Hi all,
>
> I had an embarrassing moment today, when I found that the source
of a severe performance problem was sitting in front of the screen.
>
> Using XSLT 2.0 I am transforming elements and at many points I
have to look up the ancestor axis, but only up to an element with an
attribute "id". Basically I have a deeply nested structure of topics
and I want to analyze ancestors inside the current topic.
>
> The nearest topic is easy to find:
>
> <xsl:variable name="topic" select="ancestor-or-self::*[@id][1]"
as="element()"/>
>
> And then I was doing the following to find all ancestors that
share the same "topic ancestor":
>
> <xsl:variable name="ancestors-in-topic"
>B B select="ancestor-or-self::*[ancestor-or-self::* = $topic]"
as="element()*"/>
>
> This did not what I expected and also wasted a lot of resources
because the predicate was true for all or most elements. After some
testing I went with this:
>
> <xsl:variable name="ancestors-in-topic"
>B B select="ancestor-or-self::*[ancestor-or-self::*/generate-id() =
generate-id($topic)]" as="element()*"/>
>
> Since that calculation is done very often I am wondering if
xsl:key could be used to speed things up?
>
> Any pointers are very welcome, as always, thanks,
>
> - Michael
>
> PS: My sample XML and XSLT below.
>
> <?xml version="1.0" encoding="UTF-8"?>
> <bars id="x0">
>B B <bar id="x1">
>B B B <bar id="x11">
>B B B B <bar id="x12">
>B B B B B <div>
>B B B B B B <bar id="x13">
>B B B B B B B <div>
>B B B B B B B B <p/>
>B B B B B B B </div>
>B B B B B B </bar>
>B B B B B </div>
>B B B B </bar>
>B B B </bar>
>B B </bar>
> </bars>
>
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform
<http://www.w3.org/1999/XSL/Transform>"
xmlns:xs="http://www.w3.org/2001/XMLSchema
<http://www.w3.org/2001/XMLSchema>" version="2.0">
>B B <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
>B B <xsl:strip-space elements="*"/>
>
>B B <xsl:template match="p">
>B B B <xsl:variable name="topic"
select="ancestor-or-self::*[@id][1]" as="element()"/>
>B B B <xsl:variable name="ancestors-in-topic"
select="ancestor-or-self::*[ancestor-or-self::*/generate-id() =
generate-id($topic)]" as="element()*"/>
>B B B <xsl:copy>
>B B B B <xsl:attribute name="topic" select="$topic/@id"/>
>B B B B <xsl:text>Ancestors: </xsl:text>
>B B B B <xsl:sequence select="$ancestors-in-topic/name()"/>
>B B B </xsl:copy>
>B B </xsl:template>
>
>B B <xsl:template match="* | @*">
>B B B <xsl:copy>
>B B B B <xsl:apply-templates select="@*, node()"/>
>B B B </xsl:copy>
>B B </xsl:template>
> </xsl:stylesheet>
>
>
> Expected output for <p>: <p topic="x13">Ancestors: bar div p</p>
>
---------- Forwarded message ---------- From:B Syd Bauman <s.bauman@xxxxxxxxxxxxxxxx <mailto:s.bauman@xxxxxxxxxxxxxxxx>> To:B <xsl-list@xxxxxxxxxxxxxxxxxxxxxx <mailto:xsl-list@xxxxxxxxxxxxxxxxxxxxxx>> Cc: Bcc: Date:B Wed, 30 Aug 2017 15:18:54 -0400 Subject:B Re: [xsl] Can I use xsl:key to select elements up to certain ancestor I think there may be a more efficient way to do this overall, but certainly if you declare those @id attributes as ID, then you could use the id() function. E.g.:
--------- <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform <http://www.w3.org/1999/XSL/Transform>" B B B B B B B B xmlns:xs="http://www.w3.org/2001/XMLSchema <http://www.w3.org/2001/XMLSchema>" version="2.0">
B <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/> B <xsl:strip-space elements="*"/>
B <xsl:template match="p"> B B <xsl:variable name="topicID" select="ancestor-or-self::*[@id][1]/@id"/> B B <xsl:variable name="ancestors-in-topic" B B B B B B B B B B B B select="ancestor-or-self::*[ B B B B ancestor-or-self::* intersect id($topicID) B B B B ]"/> B B <xsl:copy> B B B <xsl:attribute name="topic" select="$topicID"/> B B B <xsl:text>Ancestors: </xsl:text> B B B <xsl:sequence select="$ancestors-in-topic/name()"/> B B </xsl:copy> B </xsl:template>
B <xsl:template match="* | @*"> B B <xsl:copy> B B B <xsl:apply-templates select="@*, node()"/> B B </xsl:copy> B </xsl:template>
</xsl:stylesheet> ---------
works iff you declare the @id attrs as type ID:
--------- <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE bars [ <!ELEMENT bars ( bar+ )> <!ATTLIST bars id ID #IMPLIED>
<!ELEMENT bar ( bar | div )+> <!ATTLIST bar id ID #IMPLIED>
<!ELEMENT div ( bar | div | p )+> <!ELEMENT p EMPTY > ]> <bars id="x0"> B <bar id="x1"> B B <bar id="x11"> B B B <bar id="x12"> B B B B <div> B B B B B <bar id="x13"> B B B B B B <div> B B B B B B B <p/> B B B B B B </div> B B B B B </bar> B B B B </div> B B B </bar> B B </bar> B </bar> </bars> ---------
> I had an embarrassing moment today, when I found that the source of
> a severe performance problem was sitting in front of the screen.
>
> Using XSLT 2.0 I am transforming elements and at many points I have
> to look up the ancestor axis, but only up to an element with an
> attribute "id". Basically I have a deeply nested structure of
> topics and I want to analyze ancestors inside the current topic.
>
> The nearest topic is easy to find:
>
> <xsl:variable name="topic" select="ancestor-or-self::*[@id][1]"
as="element()"/>
>
> And then I was doing the following to find all ancestors that share
> the same "topic ancestor":
>
> <xsl:variable name="ancestors-in-topic"
>B B select="ancestor-or-self::*[ancestor-or-self::* = $topic]"
as="element()*"/>
>
> This did not what I expected and also wasted a lot of resources
> because the predicate was true for all or most elements. After some
> testing I went with this:
>
> <xsl:variable name="ancestors-in-topic"
>B B select="ancestor-or-self::*[ancestor-or-self::*/generate-id() =
generate-id($topic)]" as="element()*"/>
>
> Since that calculation is done very often I am wondering if xsl:key
> could be used to speed things up?
>
> Any pointers are very welcome, as always, thanks,
>
> - Michael
>
> PS: My sample XML and XSLT below.
>
> <?xml version="1.0" encoding="UTF-8"?>
> <bars id="x0">
>B B <bar id="x1">
>B B B <bar id="x11">
>B B B B <bar id="x12">
>B B B B B <div>
>B B B B B B <bar id="x13">
>B B B B B B B <div>
>B B B B B B B B <p/>
>B B B B B B B </div>
>B B B B B B </bar>
>B B B B B </div>
>B B B B </bar>
>B B B </bar>
>B B </bar>
> </bars>
>
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform
<http://www.w3.org/1999/XSL/Transform>"
xmlns:xs="http://www.w3.org/2001/XMLSchema
<http://www.w3.org/2001/XMLSchema>" version="2.0">
>B B <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
>B B <xsl:strip-space elements="*"/>
>
>B B <xsl:template match="p">
>B B B <xsl:variable name="topic"
select="ancestor-or-self::*[@id][1]" as="element()"/>
>B B B <xsl:variable name="ancestors-in-topic"
select="ancestor-or-self::*[ancestor-or-self::*/generate-id() =
generate-id($topic)]" as="element()*"/>
>B B B <xsl:copy>
>B B B B <xsl:attribute name="topic" select="$topic/@id"/>
>B B B B <xsl:text>Ancestors: </xsl:text>
>B B B B <xsl:sequence select="$ancestors-in-topic/name()"/>
>B B B </xsl:copy>
>B B </xsl:template>
>
>B B <xsl:template match="* | @*">
>B B B <xsl:copy>
>B B B B <xsl:apply-templates select="@*, node()"/>
>B B B </xsl:copy>
>B B </xsl:template>
> </xsl:stylesheet>
>
>
> Expected output for <p>: <p topic="x13">Ancestors: bar div p</p>
>
-- B Syd Bauman, EMT-Paramedic B Senior XML Programmer/Analyst B Northeastern University Women Writers Project s.bauman@xxxxxxxxxxxxxxxx <mailto:s.bauman@xxxxxxxxxxxxxxxx> or Syd_Bauman@xxxxxxxxxxxxxxxx <mailto:Syd_Bauman@xxxxxxxxxxxxxxxx>
---------- Forwarded message ---------- From:B Wolfgang Laun <wolfgang.laun@xxxxxxxxx <mailto:wolfgang.laun@xxxxxxxxx>> To:B xsl-list <xsl-list@xxxxxxxxxxxxxxxxxxxxxx <mailto:xsl-list@xxxxxxxxxxxxxxxxxxxxxx>> Cc: Bcc: Date:B Wed, 30 Aug 2017 21:24:01 +0200 Subject:B Re: [xsl] Can I use xsl:key to select elements up to certain ancestor Wouldn't assigning any element with an @id to a temporaty document and running rules against this reduce the overhead? -W
On 30 August 2017 at 21:08, David Carlisle d.p.carlisle@xxxxxxxxx <mailto:d.p.carlisle@xxxxxxxxx> <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx <mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>> wrote:
You seem to be listing ancestor-or-self rather than ancestor, I think you only need to go up the ancestor axis once in each case, something like
<xsl:stylesheet version="2.0" B B B B xmlns:xsl="http://www.w3.org/1999/XSL/Transform <http://www.w3.org/1999/XSL/Transform>">
B <xsl:template match="/"> B <xsl:apply-templates select="//p"/><!-- just for testing--> B </xsl:template>
B <xsl:template match="*"> B <xsl:copy> B B <xsl:apply-templates select="." mode="a"/> B </xsl:copy> B </xsl:template>
B <xsl:template match="*" mode="a"> B <xsl:param name="trail" select="()"/> B <xsl:apply-templates select="parent::*" mode="a"> B B <xsl:with-param name="trail" select="name(),$trail"/> B </xsl:apply-templates> B </xsl:template>
B <xsl:template match="*[@id]" mode="a"> B <xsl:param name="trail" select="()"/> B B <xsl:copy-of select="@id,'Ancestors:', name(), $trail"/> B </xsl:template>
</xsl:stylesheet>
which makes
<p id="x13">Ancestors: bar div p</p>
On 30 August 2017 at 19:49, Michael MC<ller-Hillebrand
mmh@xxxxxxxxx <mailto:mmh@xxxxxxxxx>
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx
<mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>> wrote:
> Hi all,
>
> I had an embarrassing moment today, when I found that the
source of a severe performance problem was sitting in front of
the screen.
>
> Using XSLT 2.0 I am transforming elements and at many points
I have to look up the ancestor axis, but only up to an element
with an attribute "id". Basically I have a deeply nested
structure of topics and I want to analyze ancestors inside the
current topic.
>
> The nearest topic is easy to find:
>
> <xsl:variable name="topic"
select="ancestor-or-self::*[@id][1]" as="element()"/>
>
> And then I was doing the following to find all ancestors that
share the same "topic ancestor":
>
> <xsl:variable name="ancestors-in-topic"
>B B select="ancestor-or-self::*[ancestor-or-self::* = $topic]"
as="element()*"/>
>
> This did not what I expected and also wasted a lot of
resources because the predicate was true for all or most
elements. After some testing I went with this:
>
> <xsl:variable name="ancestors-in-topic"
> B select="ancestor-or-self::*[ancestor-or-self::*/generate-id()
= generate-id($topic)]" as="element()*"/>
>
> Since that calculation is done very often I am wondering if
xsl:key could be used to speed things up?
>
> Any pointers are very welcome, as always, thanks,
>
> - Michael
>
> PS: My sample XML and XSLT below.
>
> <?xml version="1.0" encoding="UTF-8"?>
> <bars id="x0">
>B B <bar id="x1">
>B B B <bar id="x11">
>B B B B <bar id="x12">
>B B B B B <div>
>B B B B B B <bar id="x13">
>B B B B B B B <div>
>B B B B B B B B <p/>
>B B B B B B B </div>
>B B B B B B </bar>
>B B B B B </div>
>B B B B </bar>
>B B B </bar>
>B B </bar>
> </bars>
>
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform
<http://www.w3.org/1999/XSL/Transform>"
xmlns:xs="http://www.w3.org/2001/XMLSchema
<http://www.w3.org/2001/XMLSchema>" version="2.0">
>B B <xsl:output method="xml" indent="yes"
omit-xml-declaration="no"/>
>B B <xsl:strip-space elements="*"/>
>
>B B <xsl:template match="p">
>B B B <xsl:variable name="topic"
select="ancestor-or-self::*[@id][1]" as="element()"/>
>B B B <xsl:variable name="ancestors-in-topic"
select="ancestor-or-self::*[ancestor-or-self::*/generate-id() =
generate-id($topic)]" as="element()*"/>
>B B B <xsl:copy>
>B B B B <xsl:attribute name="topic" select="$topic/@id"/>
>B B B B <xsl:text>Ancestors: </xsl:text>
>B B B B <xsl:sequence select="$ancestors-in-topic/name()"/>
>B B B </xsl:copy>
>B B </xsl:template>
>
>B B <xsl:template match="* | @*">
>B B B <xsl:copy>
>B B B B <xsl:apply-templates select="@*, node()"/>
>B B B </xsl:copy>
>B B </xsl:template>
> </xsl:stylesheet>
>
>
> Expected output for <p>: <p topic="x13">Ancestors: bar div p</p>
>
---------- Forwarded message ---------- From:B Michael Kay <mike@xxxxxxxxxxxx <mailto:mike@xxxxxxxxxxxx>> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx <mailto:xsl-list@xxxxxxxxxxxxxxxxxxxxxx> Cc: Bcc: Date:B Wed, 30 Aug 2017 23:19:45 +0100 Subject:B Re: [xsl] Can I use xsl:key to select elements up to certain ancestor > > And then I was doing the following to find all ancestors that share the same "topic ancestor": > > <xsl:variable name="ancestors-in-topic" >B select="ancestor-or-self::*[ancestor-or-self::* = $topic]" as="element()*"/> > > This did not what I expected and also wasted a lot of resources because the predicate was true for all or most elements. After some testing I went with this: > > <xsl:variable name="ancestors-in-topic" >B select="ancestor-or-self::*[ancestor-or-self::*/generate-id() = generate-id($topic)]" as="element()*"/>
You're looking for ancestors of the context item that are descendants of $topic (with a possible -or-self thrown in).
The challenge here is to avoid making this quadratic in the length of the ancestor axis. Your code is effectively saying "for every ancestor, find every ancestor and test it".
Use of the "=" operator is a bad mistake: this compares string values of nodes, which involves examining all the descendants: it's not only inefficient, it also gives the wrong answer.
I think the simplest solution is (ancestor-or-self::* except $topic/ancestor::*) but this is still rather inefficient (it will also return nodes in document order so you may need to reverse() the result). I've often wished there was an "until" operator in XPath that selects all items in a sequence up to the first where a condition is true:
ancestor-or-self::* until (self::* is $topic)
and you can write this yourself as a higher-order extension function in 3.0:
<xsl:function name="f:until" as="item()*"> B <xsl:param name="seq" as="item()*"/> B <xsl:param name="condition" as="function(item()) as xs:boolean"/> B <xsl:sequence select=" B B B if (empty($seq)) B B B then () B B B else if ($condition(head($seq)) B B B then head($seq) B B B else (head($seq), f:until(tail($seq), $condition))"/> </xsl:function>
and you could invoke this as
f:until(ancestor-or-self::*, function($x){$x is $topic})
Of course you could also write a less generic recursive function:
<xsl:function name="nodes-until" as="item()*"> B <xsl:param name="seq" as="item()*"/> B <xsl:param name="target" as="node()"/> B <xsl:sequence select=" B B B if (empty($seq)) B B B then () B B B else if ($target is head($seq)) B B B then head($seq) B B B else (head($seq), nodes-until(tail($seq), $target))"/> </xsl:function>
f:nodes-until(ancestor::*, $topic)
Michael Kay Saxonica
> <xsl:variable name="ancestors-in-topic" >B select="ancestor-or-self::*[some $ancestor-or-self::* is $topic)]" as="element()*"/>
>
> Since that calculation is done very often I am wondering if
xsl:key could be used to speed things up?
>
> Any pointers are very welcome, as always, thanks,
>
> - Michael
>
> PS: My sample XML and XSLT below.
>
> <?xml version="1.0" encoding="UTF-8"?>
> <bars id="x0">
>B <bar id="x1">
>B B <bar id="x11">
>B B B <bar id="x12">
>B B B B <div>
>B B B B B <bar id="x13">
>B B B B B B <div>
>B B B B B B B <p/>
>B B B B B B </div>
>B B B B B </bar>
>B B B B </div>
>B B B </bar>
>B B </bar>
>B </bar>
> </bars>
>
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform
<http://www.w3.org/1999/XSL/Transform>"
xmlns:xs="http://www.w3.org/2001/XMLSchema
<http://www.w3.org/2001/XMLSchema>" version="2.0">
>B <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
>B <xsl:strip-space elements="*"/>
>
>B <xsl:template match="p">
>B B <xsl:variable name="topic"
select="ancestor-or-self::*[@id][1]" as="element()"/>
>B B <xsl:variable name="ancestors-in-topic"
select="ancestor-or-self::*[ancestor-or-self::*/generate-id() =
generate-id($topic)]" as="element()*"/>
>B B <xsl:copy>
>B B B <xsl:attribute name="topic" select="$topic/@id"/>
>B B B <xsl:text>Ancestors: </xsl:text>
>B B B B <xsl:sequence select="$ancestors-in-topic/name()"/>
>B B </xsl:copy>
>B </xsl:template>
>
>B <xsl:template match="* | @*">
>B B <xsl:copy>
>B B B <xsl:apply-templates select="@*, node()"/>
>B B </xsl:copy>
>B </xsl:template>
> </xsl:stylesheet>
>
>
> Expected output for <p>: <p topic="x13">Ancestors: bar div p</p>
>
---------- Forwarded message ---------- From:B Rahul Singh <rahulsinghindia15@xxxxxxxxx <mailto:rahulsinghindia15@xxxxxxxxx>> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx <mailto:xsl-list@xxxxxxxxxxxxxxxxxxxxxx>, "XSL-List: The Open Forum on XSL" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx <mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>> Cc: Bcc: Date:B Thu, 31 Aug 2017 08:57:33 +0530 Subject:B XSL matching and duplication! Hi,
i need data from input1.xml check first if clientname/id is matching with clientdata/name from input2.xml otherwise delete duplication based on clientname/Email from input1.xml, My duplication is working but i am not geetitng first condition data:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform <http://www.w3.org/1999/XSL/Transform>"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:key name="kBymail" match="clientname" use="Email"/> <xsl:template match="node() | @*"> <xsl:copy> <xsl:apply-templates select="node() | @*"/> </xsl:copy> </xsl:template> <xsl:template match="clientname[Email = following-sibling::clientname/Email]"/> </xsl:stylesheet>
Input1.xml: ------------------------------------------------ <?xml version="1.0" encoding="UTF-8"?> <ClientInfo> B B <clientname> B B B B <Id>003f40000049yJYAAY</Id> B B B B <Email>gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx></Email> B B B </clientname> B B <clientname> B B B B <Id>003f40000049z3iAAA</Id> B B B B <Email>gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx></Email> B B B </clientname> B B <clientname> B B B B <Id>003f40000049z3nAAA</Id> B B B B <Email>gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx></Email> B B B </clientname> B B <clientname> B B B B <Id>003f40000048uLLAAY</Id> B B B B <Email>gar@xxxxxxxxx <mailto:gar@xxxxxxxxx></Email> B B B </clientname> B B <clientname> B B B B <Id>003f40000049t38AAA</Id> B B B B <Email>gad@xxxxxxxxx <mailto:gad@xxxxxxxxx></Email> B B B </clientname> B </objects>
Input2.xml: --------------------------------------- B <?xml version="1.0" encoding="UTF-8"?> <ClientInfo> B B <clientdata> B B B B <name>003f40000048uLLAAY</name> B B B <clientnameReference> B B B B B B <Email>gar@xxxxxxxxx <mailto:gar@xxxxxxxxx></Email> B B B B </clientnameReference> B B B </clientdata> B B <clientdata> B B B B <name>003f40000049t38AAA</name> B B B <clientnameReference> B B B B B B <Email>gad@xxxxxxxxx <mailto:gad@xxxxxxxxx></Email> B B B B </clientnameReference> B B B </clientdata> B B <clientdata> B B B B <name>003f40000049yJYAAY</name> B B B <clientnameReference> B B B B B B <Email>gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx></Email> B B B B </clientnameReference> B B B </clientdata> B </objects>
Expectedoutput: --------------------------------------- <?xml version="1.0" encoding="UTF-8"?> <ClientInfo> B B <clientname> B B B B <Id>003f40000049yJYAAY</Id> B B B B <Name>barcode11</Name> B B B B <Email>gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx></Email> B B B </clientname> B B <clientname> B B B B <Id>003f40000048uLLAAY</Id> B B B B <Name>Bob Robben</Name> B B B B <Email>gar@xxxxxxxxx <mailto:gar@xxxxxxxxx></Email> B B B </clientname> B B <clientname> B B B B <Id>003f40000049t38AAA</Id> B B B B <Name>ADVT4</Name> B B B B <Email>gad@xxxxxxxxx <mailto:gad@xxxxxxxxx></Email> B B B </clientname> B </objects>
---------- Forwarded message ---------- From:B "Imsieke, Gerrit, le-tex" <gerrit.imsieke@xxxxxxxxx <mailto:gerrit.imsieke@xxxxxxxxx>> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx <mailto:xsl-list@xxxxxxxxxxxxxxxxxxxxxx> Cc: Bcc: Date:B Thu, 31 Aug 2017 08:01:05 +0200 Subject:B Re: [xsl] XSL matching and duplication! Hi Rahul,
A couple of observations/questions:
b Assuming that you invoke the transformation with Input1.xml as the source, how does the stylesheet ever get to know Input2.xml in order to do any comparisons with clientdata/name? If Input1.xml is the input, I would have expected something like <xsl:variable name="Input2" as="document-node(element(ClientInfo))" select="doc('Input2.xml')"/> in the stylesheet.
b What exactly should happen if clientname/Id of Input1.xml matches clientdata/name of Input2.xml, and what should happen if it doesnbt? In particular, the records of which file should be de-duplicated, Input1.xmlbs clientname records or Input2.xml? Your expected output suggests that Input1.xmlbs records should be de-duplicated. What should happen if there is no match for clientdata/name in Input2.xml? As I understood the requirement, then no de-duplication should occur. Ibm not sure whether this is your intention.
b Finally, where do the Name fields stem from in the expected output? They are not present in any of the inputs.
These are the essential questions. In addition, a couple of other things did not go unnoticed:
b You declare a key named 'kBymail', but you donbt use it.
b The start and end tags of the top-level elements in Input1.xml and Input2.xml donbt match.
b You are comparing the clientname/Email element with the Email element of all following siblings. This can become a performance issue for large data sets. Consider using <xsl:for-each-group select="clientname" group-by="Email"> for de-duplication.
Gerrit
On 31.08.2017 05:27, Rahul Singh rahulsinghindia15@xxxxxxxxx <mailto:rahulsinghindia15@xxxxxxxxx> wrote:
Hi,
i need data from input1.xml check first if clientname/id is matching with clientdata/name from input2.xml otherwise delete duplication based on clientname/Email from input1.xml, My duplication is working but i am not geetitng first condition data:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform <http://www.w3.org/1999/XSL/Transform>"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:key name="kBymail" match="clientname" use="Email"/> <xsl:template match="node() | @*"> <xsl:copy> <xsl:apply-templates select="node() | @*"/> </xsl:copy> </xsl:template> <xsl:template match="clientname[Email = following-sibling::clientname/Email]"/> </xsl:stylesheet>
Input1.xml: ------------------------------------------------ <?xml version="1.0" encoding="UTF-8"?> <ClientInfo> B B B <clientname> B B B B B <Id>003f40000049yJYAAY</Id> B B B B B <Email>gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx> <mailto:gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx>></Email> B B B B </clientname> B B B <clientname> B B B B B <Id>003f40000049z3iAAA</Id> B B B B B <Email>gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx> <mailto:gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx>></Email> B B B B </clientname> B B B <clientname> B B B B B <Id>003f40000049z3nAAA</Id> B B B B B <Email>gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx> <mailto:gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx>></Email> B B B B </clientname> B B B <clientname> B B B B B <Id>003f40000048uLLAAY</Id> B B B B B <Email>gar@xxxxxxxxx <mailto:gar@xxxxxxxxx> <mailto:gar@xxxxxxxxx <mailto:gar@xxxxxxxxx>></Email> B B B B </clientname> B B B <clientname> B B B B B <Id>003f40000049t38AAA</Id> B B B B B <Email>gad@xxxxxxxxx <mailto:gad@xxxxxxxxx> <mailto:gad@xxxxxxxxx <mailto:gad@xxxxxxxxx>></Email> B B B B </clientname> B B </objects>
Input2.xml: --------------------------------------- B B <?xml version="1.0" encoding="UTF-8"?> <ClientInfo> B B B <clientdata> B B B B B <name>003f40000048uLLAAY</name> B B B B <clientnameReference> B B B B B B B <Email>gar@xxxxxxxxx <mailto:gar@xxxxxxxxx> <mailto:gar@xxxxxxxxx <mailto:gar@xxxxxxxxx>></Email> B B B B B </clientnameReference> B B B B </clientdata> B B B <clientdata> B B B B B <name>003f40000049t38AAA</name> B B B B <clientnameReference> B B B B B B B <Email>gad@xxxxxxxxx <mailto:gad@xxxxxxxxx> <mailto:gad@xxxxxxxxx <mailto:gad@xxxxxxxxx>></Email> B B B B B </clientnameReference> B B B B </clientdata> B B B <clientdata> B B B B B <name>003f40000049yJYAAY</name> B B B B <clientnameReference> B B B B B B B <Email>gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx> <mailto:gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx>></Email> B B B B B </clientnameReference> B B B B </clientdata> B B </objects>
Expectedoutput: --------------------------------------- <?xml version="1.0" encoding="UTF-8"?> <ClientInfo> B B B <clientname> B B B B B <Id>003f40000049yJYAAY</Id> B B B B B <Name>barcode11</Name> B B B B B <Email>gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx> <mailto:gbc@xxxxxxxxx <mailto:gbc@xxxxxxxxx>></Email> B B B B </clientname> B B B <clientname> B B B B B <Id>003f40000048uLLAAY</Id> B B B B B <Name>Bob Robben</Name> B B B B B <Email>gar@xxxxxxxxx <mailto:gar@xxxxxxxxx> <mailto:gar@xxxxxxxxx <mailto:gar@xxxxxxxxx>></Email> B B B B </clientname> B B B <clientname> B B B B B <Id>003f40000049t38AAA</Id> B B B B B <Name>ADVT4</Name> B B B B B <Email>gad@xxxxxxxxx <mailto:gad@xxxxxxxxx> <mailto:gad@xxxxxxxxx <mailto:gad@xxxxxxxxx>></Email> B B B B </clientname> B B </objects>
XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list <http://www.mulberrytech.com/xsl/xsl-list>> EasyUnsubscribe <-list/225679 <-list/225679>> (by email < <>?subject=remove>)
-- Gerrit Imsieke
GeschC$ftsfC<hrer / Managing Director
le-tex publishing services GmbH
Weissenfelser Str. 84, 04229 Leipzig, Germany
Phone +49 341 355356 110, Fax +49 341 355356 510
gerrit.imsieke@xxxxxxxxx <mailto:gerrit.imsieke@xxxxxxxxx>,
http://www.le-tex.de
Registergericht / Commercial Register: Amtsgericht Leipzig Registernummer / Registration Number: HRB 24930
GeschC$ftsfC<hrer: Gerrit Imsieke, Svea Jelonek, Thomas Schmidt, Dr. Reinhard VC6ckler
-- Gerrit Imsieke GeschC$ftsfC<hrer / Managing Director le-tex publishing services GmbH Weissenfelser Str. 84, 04229 Leipzig, Germany Phone +49 341 355356 110, Fax +49 341 355356 510 gerrit.imsieke@xxxxxxxxx, http://www.le-tex.de
Registergericht / Commercial Register: Amtsgericht Leipzig Registernummer / Registration Number: HRB 24930
GeschC$ftsfC<hrer: Gerrit Imsieke, Svea Jelonek, Thomas Schmidt, Dr. Reinhard VC6ckler
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] XSL matching and duplicat, Imsieke, Gerrit, le- | Thread | |
Re: [xsl] XSL matching and duplicat, Imsieke, Gerrit, le- | Date | |
Month |