<br><div class="gmail_quote">On Tue, Feb 26, 2008 at 8:21 AM, Wei, Alice J. &lt;<a href="mailto:ajwei@indiana.edu">ajwei@indiana.edu</a>&gt; wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Hi, David:<br>
<br>
 &nbsp;I think I am having a different issue different from what I had several weeks ago.<br>
 &nbsp; What I have modified is from:<br>
<br>
let $ad := fn:collection(&quot;xmldb:exist://db/cbml&quot;)//ad/p[contains(upper-case(.), &#39;BOOK&#39;)]<br>
let $sorted_result:=<br>
for $doc in distinct-values($ad)<br>
order by $doc<br>
return $doc<br>
for $r at $count in $sorted_result<br>
let $nodes := $ad[. = $r][1]<br>
return<br>
&lt;ad&gt;<br>
{$nodes}<br>
&lt;/ad&gt;<br></blockquote><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
 &nbsp;by trying to put it in user-defined functions, which is currently giving me quite a bit of problems from itself.<br>
<div class="Ih2E3d"><br>
declare boundary-space preserve;<br>
declare function local:distinct(<br>
 &nbsp; &nbsp; $seq as xs:anyAtomicType*)<br>
 &nbsp; &nbsp; &nbsp;as xs:anyAtomicType<br>
&nbsp;{<br>
</div>&nbsp;let $doc := distinct-values($seq)<br>
<div class="Ih2E3d">&nbsp;order by $doc<br>
&nbsp;return<br>
 &nbsp;&lt;ad&gt;{$doc} &lt;/ad&gt;<br>
&nbsp;};<br>
<br>
</div>&nbsp;for $ad in<br>
distinct-values(collection(&quot;xmldb:exist://db/cbml&quot;)//ad/p[contains(upper-case(.$<br>
<div class="Ih2E3d">&nbsp;return<br>
&lt;ad&gt;{local:distinct($ad)}&lt;/ad&gt;<br>
<br>
</div>As I mentioned before, I only intend to have the output be appeared in the same way as the above XQuery that is not in the function.<br>
Is this possible?<br>
<br>
Thanks for your help.<br>
<div class="Ih2E3d">======================================================<br>
Alice Wei<br>
MIS 2008<br>
School of Library and Information Science<br>
Indiana University Bloomington<br>
<a href="mailto:ajwei@indiana.edu">ajwei@indiana.edu</a><br>
________________________________________<br>
</div>From: David Carlisle [<a href="mailto:davidc@nag.co.uk">davidc@nag.co.uk</a>]<br>
Sent: Tuesday, February 26, 2008 10:33 AM<br>
To: Wei, Alice J.<br>
Cc: <a href="mailto:talk@x-query.com">talk@x-query.com</a><br>
Subject: Re: [xquery-talk] Function and Query Evaluation with No XML Tags Error<br>
<div><div></div><div class="Wj3C7c"><br>
Alice,<br>
<br>
Alice it seems hard to help as you have been essentially posting the<br>
same code, with the same error for weeks,<br>
<br>
When you go<br>
<br>
&nbsp;for $ad in distinct-values(...anything)<br>
<br>
then, on each iteration $ad will be a single string (one of the values)<br>
<br>
So on each call to local:distinct($ad) you are passing in a single string. so<br>
doing operations such as distinct-values() or for or order by are all<br>
essentialy null-operations. It&#39;s not an error to take all the<br>
unique values from a sequence of length one and then sort them, but you will always<br>
just get back the value you started with.<br>
<br>
<br>
See for example:<br>
<br>
<a href="http://x-query.com/pipermail/talk/2008-January/002436.html" target="_blank">http://x-query.com/pipermail/talk/2008-January/002436.html</a><br>
<br>
David<br>
<br></div></div></blockquote></div><br>
distinct-values returns a list of values (strings) NOT elements.&nbsp;
(hence the &#39;values&#39;).&nbsp;&nbsp; It&#39;s throwing away all of the XML element markup and just
keeping the string values (all smashed together).<br>
<br>Example XML file:<br>&lt;?xml version=&quot;1.0&quot;?&gt;<br>&lt;data&gt;<br>&nbsp; &lt;record&gt;<br>&nbsp;&nbsp;&nbsp; &lt;name&gt;Fred Flinstone&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp; &lt;street&gt;Fred&#39;s Street&lt;/street&gt;<br>&nbsp; &lt;/record&gt;<br>
&nbsp; &lt;record&gt;<br>&nbsp;&nbsp;&nbsp; &lt;name&gt;Fred Flinstone&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp; &lt;street&gt;Fred&#39;s Street&lt;/street&gt;<br>&nbsp; &lt;/record&gt;<br>&nbsp; &lt;record&gt;<br>&nbsp;&nbsp;&nbsp; &lt;name&gt;Barney Rubble&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp; &lt;street&gt;Barney&#39;s Street&lt;/street&gt;<br>
&nbsp; &lt;/record&gt;<br>&nbsp; &lt;record&gt;<br>&nbsp;&nbsp;&nbsp; &lt;name&gt;Wilma Flinstone&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp; &lt;street&gt;Wilma&#39;s Street&lt;/street&gt;<br>&nbsp; &lt;/record&gt;<br>&nbsp; &lt;record&gt;<br>&nbsp;&nbsp;&nbsp; &lt;name&gt;Betty Rubble&lt;/name&gt;<br>
&nbsp;&nbsp;&nbsp; &lt;street&gt;Betty&#39;s Street&lt;/street&gt;<br>&nbsp; &lt;/record&gt;<br>&lt;/data&gt;<br><br>NOTICE: Fred&#39;s entry is duplicated!<br><br>Example Query:<br>for $r in distinct-values(/data/record)<br>return $r<br><br>
<br>Results:<br>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br>&nbsp;&nbsp;&nbsp; Fred Flinstone<br>&nbsp;&nbsp;&nbsp; Fred&#39;s Street<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Barney Rubble<br>&nbsp;&nbsp;&nbsp; Barney&#39;s Street<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Wilma Flinstone<br>&nbsp;&nbsp;&nbsp; Wilma&#39;s Street<br>
&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Betty Rubble<br>&nbsp;&nbsp;&nbsp; Betty&#39;s Street<br>&nbsp; <br>NOTICE: No XML markup.&nbsp; It was all stripped.&nbsp; It&#39;s like calling string on it: &lt;record&gt;&lt;name&gt; and &lt;street&gt; have been removed: the data flattened into a string.<br>
<br>It&#39;s like this:<br><br>for $r in /data/record<br>return string($r)<br><br><br>Results:<br>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br>&nbsp;&nbsp;&nbsp; Fred Flinstone<br>&nbsp;&nbsp;&nbsp; Fred&#39;s Street<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Fred Flinstone<br>
&nbsp;&nbsp;&nbsp; Fred&#39;s Street<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Barney Rubble<br>&nbsp;&nbsp;&nbsp; Barney&#39;s Street<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Wilma Flinstone<br>&nbsp;&nbsp;&nbsp; Wilma&#39;s Street<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Betty Rubble<br>&nbsp;&nbsp;&nbsp; Betty&#39;s Street<br>&nbsp; <br>Again: no XML markup.&nbsp; They&#39;re strings (because I explicitly converted them to strings).&nbsp; However, this time, I DID get the duplicated entry for Fred.<br>
<br>Will you really have different nodes (with subnodes) that contain completely duplicated data?&nbsp; If so, I have no suggestions.&nbsp; If not and you&#39;re really getting multiple instances of the SAME node, then use the id function to test for uniqueness.<br>
<br>I figured I could use this:<br>(: ** Generates runtime errror ** :)<br>for $r in /data/record[not(string(.)=string(preceding::*))]<br>return string($r)<br><br>But it generates a complaint (at runtime): <br>Description: A sequence of more than one item is not allowed as the first argument of string() (&lt;record/&gt;, &lt;name/&gt;, ...) <br>
** SEE More at the bottom: I figured it out.<br><br>I tried a few other things to get distinct nodes based on the content, but none of the others would even parse : I&#39;m still mostly in the dark about the magic of XQuery and XPath.<br>
<br>Try removing the disctinct-values (and iterate over the elements) and you may get something closer to what you are expecting.<br><br>** (corrected from above)<br>Here&#39;s a unique by value<br>for $r in /data/record[not(string(.)=string((preceding-sibling::*)[1]))]<br>
return string($r)<br><br>Results:<br>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br>&nbsp;&nbsp;&nbsp; Fred Flinstone<br>&nbsp;&nbsp;&nbsp; Fred&#39;s Street<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Barney Rubble<br>&nbsp;&nbsp;&nbsp; Barney&#39;s Street<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Wilma Flinstone<br>
&nbsp;&nbsp;&nbsp; Wilma&#39;s Street<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; Betty Rubble<br>&nbsp;&nbsp;&nbsp; Betty&#39;s Street<br>&nbsp; <br>Again.&nbsp; It&#39;s unique (because I made it unique in the XPath), but it&#39;s iterating over the nodes.&nbsp; It&#39;s a string, because I explicitly convert them to strings.&nbsp; I could have also done:<br>
<br>for $r in /data/record[not(string(.)=string((preceding-sibling::*)[1]))]<br>return normalize-space($r)<br><br><br>Results:<br>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;Fred Flinstone Fred&#39;s Street Barney Rubble Barney&#39;s Street Wilma Flinstone Wilma&#39;s Street Betty Rubble Betty&#39;s Street<br>
<br>NOTICES: it all a string (because normalize-space converts things to string) but &#39;extra&#39; whitespace is stripped.<br><br>Or:<br>for $r in /data/record[not(string(.)=string((preceding-sibling::*)[1]))]<br>return &lt;newelement&gt;{normalize-space($r)}&lt;/newelement&gt;<br>
<br>Results:<br>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br>&lt;newelement&gt;Fred Flinstone Fred&#39;s Street&lt;/newelement&gt;<br>&lt;newelement&gt;Barney Rubble Barney&#39;s Street&lt;/newelement&gt;<br>
&lt;newelement&gt;Wilma Flinstone Wilma&#39;s Street&lt;/newelement&gt;<br>&lt;newelement&gt;Betty Rubble Betty&#39;s Street&lt;/newelement&gt;<br><br>NOTICE: String results wrapped in a new tag.<br><br>Or:<br>for $r in /data/record[not(string(.)=string((preceding-sibling::*)[1]))]<br>
return &lt;newelement&gt;{$r}&lt;/newelement&gt;<br><br>Results:<br>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br>&lt;newelement&gt;<br>&nbsp;&nbsp; &lt;record&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;Fred Flinstone&lt;/name&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;street&gt;Fred&#39;s Street&lt;/street&gt;<br>&nbsp; &lt;/record&gt;<br>&lt;/newelement&gt;<br>&lt;newelement&gt;<br>&nbsp;&nbsp; &lt;record&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;Barney Rubble&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;street&gt;Barney&#39;s Street&lt;/street&gt;<br>
&nbsp; &lt;/record&gt;<br>&lt;/newelement&gt;<br>&lt;newelement&gt;<br>&nbsp;&nbsp; &lt;record&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;Wilma Flinstone&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;street&gt;Wilma&#39;s Street&lt;/street&gt;<br>&nbsp; &lt;/record&gt;<br>&lt;/newelement&gt;<br>
&lt;newelement&gt;<br>&nbsp;&nbsp; &lt;record&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;name&gt;Betty Rubble&lt;/name&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;street&gt;Betty&#39;s Street&lt;/street&gt;<br>&nbsp; &lt;/record&gt;<br>&lt;/newelement&gt;<br><br>NOTICE: Original XML elements (and sub elements) wrapped in a new tag.<br>
<br>Or, if you plan on using that &#39;logic&#39; over and over, you can create a function for it:<br><br>XQuery: This is the same as (functionally) the previous example, it just defines (and uses) a local function<br><br>
declare function local:unique-nodes-by-value($seq as element()*) as element()*<br>{<br>&nbsp; for $r in $seq[not(string(.)=string((preceding-sibling::*)[1]))]<br>&nbsp; return $r<br>};<br><br>for $r in local:unique-nodes-by-value(/data/record)<br>
return &lt;newelement&gt;{$r}&lt;/newelement&gt;<br><br>Using XPaths, you can pick and choose what element/sub element (values, content, or sub-content) you get.<br><br>I hope this helps some.<br><br>Keep in mind, I&#39;m relatively new at this so there are probably better ways.<br>
<br>- Kevin<br><br>