Check duplicate item in OUTPUT

I have XML, for example, it looks like this:

<root> <field1>test</field1> <f2>t2</f2> <f2>t3</f2> </root> 

I want to convert it using XSLT, but I want to suppress the second f2 element in the output - how can I check inside my template to see if the f2 element exists in the output when the second f2 element in the source is processed? Currently my XSLT looks something like this:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="no" omit-xml-declaration="yes" standalone="no" /> <xsl:template match="/"> <xsl:for-each select="./root"> <output> <xsl:apply-templates /> </output> </xsl:for-each> </xsl:template> <xsl:template match="*" > <xsl:element name="{name(.)}"> <xsl:value-of select="." /> </xsl:element> </xsl:template> </xsl:stylesheet> 

I need to do some checking around the xsl: element in a template that I think, but I'm not sure how to poll the output document to see if this element is present.

Edit: I forgot the preliminary tags, the code should be visible right now!

+4
source share
3 answers

It depends on how much you want to be systematic.

i.e. You are only interested in elements that are children of the same parent, or all elements on the same level ("cousins" if you want) or elements anywhere in the document ...

In the first situation, you can check the axis of the previous brother to see if there are any other elements with the same name.

 <xsl:if test="count(preceding-sibling::node()[name()=name(current())])=0"> ... do stuff in here. </xsl:if> 
+7
source

To check (and warn about duplication), you can find here

Something along the lines of:

 <xsl:for-each-group select="collection(...)//@id" group-by="."> <xsl:if test="count(current-group()) ne 1"> <xsl:message>Id value <xsl:value-of select="current-grouping-key()"/> is duplicated in files <xsl:value-of select="current-group()/document-uri(/)" separator=" and "/></xsl:message> </xsl:if> </xsl:for-each-group> 

To change all nodes in the root element.

Regarding removing duplicate rows, you have another one here

It will look like this:

 <xsl:stylesheet> <xsl:key name="xyz" match="record[x/y/z]" use="x/y/z" /> <xsl:variable name="noxyzdups" select="/path/to/record[generate-id(.) = generate-id(key('xyz', x/y/z))]" /> ... <xsl:template ... > <xsl:copy-of "exslt:node-set($noxyzdups)" /> </xsl:template> </xsl:stylesheet> 

x / y / z is the xpath expression that you want to make unique. It could be concat (x, '-', @y, '-', z) or whatever.

Now I'm not sure if these two examples can be easily adapted to your case, but I just wanted to point out these two sources if that helps.

+1
source

Unable to interrogate the output of your conversion. It is also impossible to keep track of the current state of your conversion (i.e., keep track of which nodes you selected in a variable). Essentially, this is not how XSLT works. One of the costs of a free software environment is that you cannot do something that has side effects. Oh good.

In your case, one way to achieve this would be to create a variable containing a list of all the source elements that can be converted to an output element that you want to release only once. Then check each node that you transform into this list. If it is not listed, release it. If this is the first item on the list, release it. Otherwise, do not.

+1
source

Source: https://habr.com/ru/post/1277360/


All Articles