XQuery - Filter deep child nodes for duplicates - duplicates

I am trying to remove duplicates on a lower level under my elements, as they can not be processed in the system. Unfortunately without much success so far.
The XML has several <Article> childs under <Articles>. The <Article> Elements can have <UNIT> Elements. These need to be unique in the whole document, but only the <NR>/<COUNT> combination.
With the Example as followed:
<Articles>
<Article>
<A1>123</A1>
<A2>456</A2>
<UNIT>
<NR>59</NR>
<COUNT>3</COUNT>
<TEXT>RANDOM Aqfwfqf</TEXT>
</UNIT>
<UNIT>
<NR>59</NR>
<COUNT>3</COUNT>
<TEXT>RANDOM hrthe</TEXT>
</UNIT>
<UNIT>
<NR>59</NR>
<COUNT>59</COUNT>
<TEXT>RANDOM cutrh</TEXT>
</UNIT>
</Article>
<Article>
<A1>351</A1>
<A2>362</A2>
<UNIT>
<NR>59</NR>
<COUNT>4</COUNT>
<TEXT>RANDOM rtjrtf</TEXT>
</UNIT>
<UNIT>
<NR>59</NR>
<COUNT>3</COUNT>
<TEXT>RANDOM jrtj</TEXT>
</UNIT>
<UNIT>
<NR>59</NR>
<COUNT>59</COUNT>
<TEXT>RANDOM rtjrt</TEXT>
</UNIT>
</Article>
</Articles>
The result should look like:
<Articles>
<Article>
<A1>123</A1>
<A2>456</A2>
<UNIT>
<NR>59</NR>
<COUNT>3</COUNT>
<TEXT>RANDOM Aqfwfqf</TEXT>
</UNIT>
<UNIT>
<NR>59</NR>
<COUNT>59</COUNT>
<TEXT>RANDOM cutrh</TEXT>
</UNIT>
</Article>
<Article>
<A1>351</A1>
<A2>362</A2>
<UNIT>
<NR>59</NR>
<COUNT>4</COUNT>
<TEXT>RANDOM rtjrtf</TEXT>
</UNIT>
</Article>
</Articles>
I tried string-join the two values in <UNIT> and then delete the nodes, but ended up deleting all of the UNIT instead of leaving one.
Getting a distinct list and count the occurences worked, but i couldn't delete the excesss nodes.
How could i reduce the quantity of the node combination to one?

For me, the following works:
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method 'xml';
declare option output:indent 'yes';
declare context item := document {
<Articles>
<Article>
<A1>123</A1>
<A2>456</A2>
<UNIT>
<NR>59</NR>
<COUNT>3</COUNT>
<TEXT>RANDOM Aqfwfqf</TEXT>
</UNIT>
<UNIT>
<NR>59</NR>
<COUNT>3</COUNT>
<TEXT>RANDOM hrthe</TEXT>
</UNIT>
<UNIT>
<NR>59</NR>
<COUNT>59</COUNT>
<TEXT>RANDOM cutrh</TEXT>
</UNIT>
</Article>
<Article>
<A1>351</A1>
<A2>362</A2>
<UNIT>
<NR>59</NR>
<COUNT>4</COUNT>
<TEXT>RANDOM rtjrtf</TEXT>
</UNIT>
<UNIT>
<NR>59</NR>
<COUNT>3</COUNT>
<TEXT>RANDOM jrtj</TEXT>
</UNIT>
<UNIT>
<NR>59</NR>
<COUNT>59</COUNT>
<TEXT>RANDOM rtjrt</TEXT>
</UNIT>
</Article>
</Articles>
};
. transform with {
delete node for $unit in //UNIT
group by $nr := $unit/NR, $cnt := $unit/COUNT
return subsequence($unit, 2)
}
So this is doing it on an in memory context node, I think if you have a db document as the input doing
delete node for $unit in //UNIT
group by $nr := $unit/NR, $cnt := $unit/COUNT
return subsequence($unit, 2)
would work just fine.

Related

How can I use <xsl:template match=""> to match the author

I'm trying to generate an HTML file using XML and XSL (XSLT). I want to show all the books that have been written by certain author (EX "Mario Vargas Llosa"). How can I do that using the match attribute in xsl:template?
XML CODE:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="template.xsl" type="text/xsl" ?>
<library>
<book>
<title language="es">La vida está en otra parte</title>
<author>Milan Kundera</author>
<publishDate year="1973"/>
</book>
<book>
<title language="es">Pantaleón y las visitadoras</title>
<author>Mario Vargas Llosa</author>
<publishDate year="1973"/>
</book>
<book>
<title language="es">Conversación en la catedral</title>
<author>Mario Vargas Llosa</author>
<publishDate year="1969"/>
</book>
<book>
<title language="en">Poems</title>
<author>Edgar Allan Poe</author>
<publishDate year="1890"/>
</book>
<book>
<title language="fr">Les Miserables</title>
<author>Victor Hugo</author>
<publishDate year="1862"/>
</book>
<book>
<title language="es">Plenilunio</title>
<author>Antonio Muñoz Molina</author>
<publishDate year="1997"/>
</book>
</library>
XSLT CODE:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<link rel="stylesheet" href="style.css"/>
</head>
<body>
<xsl:for-each select="library/book">
<h1>Title:
<xsl:value-of select="title"/>
</h1>
<p>
<strong>Author: </strong>
<xsl:value-of select="author"/>
</p>
<p>
<strong>Publishing date: </strong>
<xsl:value-of select="publishDate/#year"/>
</p>
</xsl:for-each>
</body>
</html>
</xsl:template>
Thanks in advance.
Change your XSLT file to
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<link rel="stylesheet" href="style.css"/>
</head>
<body>
<xsl:for-each select="library/book[author='Mario Vargas Llosa']">
<h1>Title:
<xsl:value-of select="title"/>
</h1>
<p>
<strong>Author: </strong>
<xsl:value-of select="author"/>
</p>
<p>
<strong>Publishing date: </strong>
<xsl:value-of select="publishDate/#year"/>
</p>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
and your xsl:for-each will iterate over all <book>s of "Mario Vargas Llosa". So the output (in your browser) will be
One line modification in XSLT. You need to add a predicate.
<xsl:for-each select="library/book[author='Mario Vargas Llosa']">

Google Contacts API PUT Invalid XML Document

I am trying to update contact info (Nickname) through Google Contact API, but getting an Invalid XML Document error (400 Bad Request). The request that I am sending is documentation : https://developers.google.com/contacts/v3/#updating_contacts.
this is my request body:
<entry gd:etag="&quot;Qno-eTVSLit7I2A9XBJUF0kKRAY.&quot;">
<id>http://www.google.com/m8/feeds/contacts/cdatatester%40gmail.com/base/21aa268e8c9eea4c</id>
<updated>2019-01-17T15:52:03.451Z</updated>
<app:edited>2019-01-17T15:52:03.451Z</app:edited>
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact"></category>
<title>Elizabeth Bennet</title>
<content>Notes</content>
<link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*" href="https://www.google.com/m8/feeds/photos/media/cdatatester%40gmail.com/21aa268e8c9eea4c"></link>
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/cdatatester%40gmail.com/full/21aa268e8c9eea4c"></link>
<link rel="edit" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/cdatatester%40gmail.com/full/21aa268e8c9eea4c"></link>
<gd:name>
<gd:fullName>Elizabeth Bennet</gd:fullName>
<gd:givenName>Altin2</gd:givenName>
<gd:familyName>Bennet</gd:familyName>
</gd:name>
<gContact:nickname>Altin</gContact:nickname>
<gd:email rel="http://schemas.google.com/g/2005#home" address="liz#gmail.com"></gd:email>
<gd:email rel="http://schemas.google.com/g/2005#work" address="liz#example.org"></gd:email>
<gd:phoneNumber rel="http://schemas.google.com/g/2005#work" uri="tel:+1-206-555-1212">(206)555-1212</gd:phoneNumber>
<gd:phoneNumber rel="http://schemas.google.com/g/2005#home" uri="tel:+1-206-555-1213">(206)555-1213</gd:phoneNumber>
<gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#home">
<gd:formattedAddress>1600 Amphitheatre Pkwy
Mountain View
CA</gd:formattedAddress>
<gd:street>1600 Amphitheatre Pkwy</gd:street>
<gd:city>Mountain View</gd:city>
<gd:country code="CA">CA</gd:country>
</gd:structuredPostalAddress>
<gContact:userDefinedField key="Color" value="Green"></gContact:userDefinedField>
<gContact:userDefinedField key="Size" value="Medium"></gContact:userDefinedField>
<gContact:groupMembershipInfo deleted="false" href="http://www.google.com/m8/feeds/groups/cdatatester%40gmail.com/base/6"></gContact:groupMembershipInfo>
<gContact:groupMembershipInfo deleted="false" href="http://www.google.com/m8/feeds/groups/cdatatester%40gmail.com/base/782732538ae3faa4"></gContact:groupMembershipInfo>
</entry>
Is there anything wrong with my request? I cannot spot any error.

Extra empty table rows in XSLT html conversion and few other problems

I have few questions conserning XSLT to html conversion.
For some reason my xsl documents makes extra rows between every for-each loop. What can be the problem? Problem can be seen in html outputs.
Here's my xslt file
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" encoding="utf-8" media-type="text/html" />
<xsl:template match="/">
<html>
<head>
<title>KT-linjan moduulit</title>
</head>
<body>
<h1>KT-linja info</h1>
<table border="double">
<caption>Moduulit taulukoituna</caption>
<tr>
<th>identifier</th>
<th>nimi</th>
<th>kuvaus</th>
</tr>
<xsl:for-each select="production_line/unit/*">
<tr>
<td>
<xsl:value-of select="#modID" />
</td>
<td>
<xsl:value-of select="name" />
</td>
<td>
<xsl:value-of select="description" />
</td>
</tr>
</xsl:for-each>
</table>
<p>
<b>HUOM:</b>
</p>
<p>ID's of the modules are unique!</p>
<p>References between modules are correct!</p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
and XML file:
<production_line>
<unit>
<lift_module modID="LM001">
<name>Päätynostin PN1</name>
<description lang="fi">Nostaa paletin alakuljettimelta ylös Starter-moduulille</description>
<conveyor type="BELT" level="down" feed="in">
<description lang="fi">Palettikuljetin (ala)</description>
<stopper />
</conveyor>
<conveyor type="BELT" level="up" feed="out">
<description lang="fi">Palettikuljetin (ylä)</description>
<stopper />
</conveyor>
<lift_shelf>
<conveyor feed="in_out" type="BAND">
<description lang="fi">Palettikuljetin (hissitaso)</description>
<stopper />
</conveyor>
<description lang="fi">Liikkuva hissitaso</description>
</lift_shelf>
<sensor type="INDUCTIVE">
<amount>2</amount>
</sensor>
<chassis type="SAFETY" width="500" heigth="1200" length="700">
<sensor type="OPTIC">
<amount>1</amount>
</sensor>
</chassis>
</lift_module>
<connection fromIDREF="LM001" toIDREF="SM001" />
</unit>
<unit>
<starter_module modID="SM001">
<name>Starter-moduuli ST1</name>
<description lang="fi">Jakaa paletit kolmelle kuljettimelle</description>
<conveyor type="BELT">
<description lang="fi">Palettikuljetin (keski)</description>
<stopper />
</conveyor>
<conveyor type="BELT">
<description lang="fi">Palettikuljetin (syöttö1)</description>
<stopper />
</conveyor>
<conveyor type="BELT">
<description lang="fi">Palettikuljetin (syöttö2)</description>
<stopper />
</conveyor>
<crossing />
<crossing />
<crossing />
<sensor type="INDUCTIVE">
<amount>3</amount>
</sensor>
<sensor type="OPTIC">
<amount>3</amount>
</sensor>
</starter_module>
<connection fromIDREF="SM001" toIDREF="WM001" />
</unit>
<unit>
<workstation modID="WM001">
<name>Työasema TA1</name>
<description lang="fi">Sisältää vasemman ja oikean työpisteen</description>
<conveyor type="BELT">
<description lang="fi">Palettikuljetin (keski)</description>
<stopper />
</conveyor>
<conveyor type="BELT">
<description lang="fi">Palettikuljetin (vasen)</description>
<stopper>stoppari</stopper>
</conveyor>
<conveyor type="BELT">
<description lang="fi">Palettikuljetin (oikea)</description>
<stopper />
</conveyor>
<crossing />
<crossing />
<crossing />
<sensor type="INDUCTIVE">
<amount>6</amount>
</sensor>
<sensor type="OPTIC">
<amount>6</amount>
</sensor>
<switch type="push_button" operate="manual">send-painike</switch>
<switch type="switch" operate="manual">pause-kytkin</switch>
</workstation>
<connection fromIDREF="WM001" toIDREF="LM002" />
</unit>
<unit>
<lift_module modID="LM002">
<name>Päätynostin PN2</name>
<description lang="fi">Laskee paletin ylhäältä alas paluukuljettimelle</description>
<conveyor type="BELT" level="down" feed="out">
<description lang="fi">Palettikuljetin (ala)</description>
<stopper />
</conveyor>
<conveyor type="BELT" level="up" feed="in">
<description lang="fi">Palettikuljetin (ylä)</description>
<stopper />
</conveyor>
<lift_shelf>
<description lang="fi">Liikkuva hissitaso</description>
<conveyor type="BELT" feed="in_out">
<description lang="fi">Palettikuljetin (hissitaso)</description>
<stopper />
</conveyor>
</lift_shelf>
<sensor type="INDUCTIVE">
<amount>2</amount>
</sensor>
<chassis type="SAFETY" width="500" heigth="1200" length="700">
<sensor type="OPTIC">
<amount>2</amount>
</sensor>
</chassis>
</lift_module>
</unit>
</production_line>
On left is my table and on the right table in correct format.
I need to check if every identifier has unique attribute name (modID, for example LM001) and post if its unique or not. How should this check be performed?
I also need to check if iDREF atributes in XML file are properly linked. For example in the end of first node there is and check that it is correctly linked to the next modID. Any idea about this one?
It also seems to add unnecessary row between "ID's of the modules are unique!" and "References between modules are correct!" lines (where should be posted the answers of the checks).
Don't do <xsl:for-each select="production_line/unit/*">. That is too unspecific, it also matches the <connection> elements (which generate the empty rows).
Do this instead: <xsl:for-each select="production_line/unit/lift_module">.
To check whether all modID values are uniqe, try to select a duplicate:
<xsl:variable name="duplicateModIds" select="
//*/#modID[
. = preceding::*/#modID
or
. = following::*/#modID
]
" />
<xsl:choose>
<xsl:when test="$duplicateModIds">
<p>IDs of the modules are NOT unique!</p>
<!-- probably output $duplicateModIds, too -->
</xsl:when>
<xsl:otherwise>
<p>IDs of the modules are unique.</p>
</xsl:otherwise>
</xsl:choose>
Note that this can also be solved more elegantly through an XSL key, but for now the "duct tape" solution should be fine. Think about using keys when the performance of your transformation starts to drop or your requirements become more complex.
To check whether all connections are correct, simply try to select an incorrect one:
<xsl:variable name="incorrectRefs" select="
//connection[
#fromIDREF != ../*/#modID
or (
../following-sibling::unit[1]
and #toIDREF != ../following-sibling::unit[1]/*/#modID
)
]
" />
<xsl:choose>
<xsl:when test="$incorrectRefs">
<p>References between modules are NOT correct!</p>
<!-- probably output $incorrectRefs, too -->
</xsl:when>
<xsl:otherwise>
<p>References between modules are correct.</p>
</xsl:otherwise>
</xsl:choose>
also need to check if iDREF atributes in XM

Insert HTML with XBL

Following this answer, I was able to insert some text with Firefox like this
css
body
{
-moz-binding: url(foo.xml#bar);
}
foo.xml
<bindings xmlns="http://www.mozilla.org/xbl">
<binding id="bar">
<content>
Hello world
</content>
</binding>
</bindings>
However I could not find a way to insert HTML rather text using this method.
It appears that I just need to declare the XHTML namespace
<bindings xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml">
<binding id="bar">
<content>
<html:b>
Hello world
</html:b>
</content>
</binding>
</bindings>

Google Apps Script-How to get value from XmlDocument?

I am trying to get all calender details of all users. I got this successfully but its return result in Xml format as following:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<id>http://www.google.com/calendar/feeds/email-id/private/full</id>
<updated>2012-02-15T15:34:49.000Z</updated>
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/g/2005#event"/>
<title type="text">email-id</title>
<subtitle type="text">email-id</subtitle>
<link href="https://www.google.com/calendar/embed?src=email-id" rel="alternate" type="text/html"/>
<link href="https://www.google.com/calendar/feeds/email-id/private/full" rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml"/>
<link href="https://www.google.com/calendar/feeds/email-id/private/full" rel="http://schemas.google.com/g/2005#post" type="application/atom+xml"/>
<link href="https://www.google.com/calendar/feeds/email-id/private/full/batch" rel="http://schemas.google.com/g/2005#batch" type="application/atom+xml"/>
<link href="https://www.google.com/calendar/feeds/email-id/private/full?max-results=25" rel="self" type="application/atom+xml"/>
<author>
<name>Name</name>
<email>email-id</email>
</author>
<generator uri="http://www.google.com/calendar" version="1.0">Google Calendar</generator>
<openSearch:totalResults xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">1</openSearch:totalResults>
<openSearch:startIndex xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">1</openSearch:startIndex>
<openSearch:itemsPerPage xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/">25</openSearch:itemsPerPage>
<gCal:timezone value="Europe/Dublin" xmlns:gCal="http://schemas.google.com/gCal/2005"/>
<gCal:timesCleaned value="0" xmlns:gCal="http://schemas.google.com/gCal/2005"/>
<entry>
<id>http://www.google.com/calendar/feeds/email-id/private/full/vj39u2qedgphrp10nah92h6ho0</id>
<published>2012-02-15T11:21:54.000Z</published>
<updated>2012-02-15T11:21:54.000Z</updated>
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/g/2005#event"/>
<title type="text">Test Appointment</title>
<content type="text">This is a test description</content>
<link href="https://www.google.com/calendar/event?eid=dmozOXUycWVkZ3BocnAxMG5haDkyaDZobzAgcmFoaW1AZGFtc2" rel="alternate" title="alternate" type="text/html"/>
...
</entry>
</feed>
I want to get the value of title and content.Please share me with the solution
Thank you
Use the built-in Xml service https://developers.google.com/apps-script/service_xml.
With this sevice you can parse thru the xml document.