I am working with a file which looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item sort="gruun">
<entrycl>
<entry>gruun</entry>
<gramt>bn</gramt></entrycl>
<translcl>
<transl>green</transl>
</translcl>
</item>
<item>
<entrycl placeatentry="gruun">
<entryx>it is grün</entryx>
</entrycl>
<translcl><transl>bla bla bla</transl>
</translcl>
</item>
<item>
<entrycl placeatentry="blue">
<entryx>it is blue</entryx></entrycl>
<translcl>
<transl>blu blu blu</transl>
</translcl>
</item>
</items>
I want to add an entrycl/entry with the value of @placeatentry, but only if there is no other item with this value. In order to facilitate checking the result I want to put an attribute (new ="yes").
The expected outcome is this:
<items>
<item sort="gruun">
<entrycl>
<entry>gruun</entry>
<gramt>bn</gramt></entrycl>
<translcl>
<transl>ble ble ble</transl>
<rem>existing item</rem>
</translcl>
</item>
<item>
<entrycl placeatentry="gruun">
<entryx>it is grün</entryx>
</entrycl>
<translcl><transl>bla bla bla</transl>
</translcl>
</item>
<item>
<entrycl new="yes">
<entry>blue</entry>
<entryx>it is blue</entryx></entrycl>
<translcl>
<transl>blu blu blu</transl>
</translcl>
</item>
</items>
Only the blue should a new entrycl/entry because there is no existing entrycl/entry with the value 'blue'.
The next step is to connect the items which did not get a new entrycl to the existing item, but I think how to do that.
I tried numerous times, benefitting from answers to other questions. Now I have this xslt file:
<?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" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item[entrycl/@placeatentry and not(//entry[.=entrycl/@placeatentry])]">
<xsl:copy>
<entrycl>
<entry new="yes">
<xsl:value-of select="entrycl/@placeatentry"/>
</entry>
<xsl:apply-templates select="entrycl/node()"/>
</entrycl>
<xsl:apply-templates select="@*|node()[not(self::entrycl)]"/>
</xsl:copy>
<!-- </xsl:if> -->
</xsl:template>
</xsl:stylesheet>
Yet my stylesheet places a new entry to all items:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item sort="gruun">
<entrycl>
<entry>gruun</entry>
<gramt>bn</gramt>
</entrycl>
<translcl>
<transl>green</transl>
</translcl>
</item>
<item>
<entrycl>
<entry new="yes">gruun</entry>
<entryx>it is grün</entryx>
</entrycl>
<translcl>
<transl>bla bla bla</transl>
</translcl>
</item>
<item>
<entrycl>
<entry new="yes">blue</entry>
<entryx>it is blue</entryx>
</entrycl>
<translcl>
<transl>blu blu blu</transl>
</translcl>
</item>
</items>
What am I doing wrong? Am I overlooking something? Thank you in advance for your help.
CodePudding user response:
See if this simplified example can get you on the right track:
XML
<items>
<item>
<entrycl>
<entry>gruun</entry>
</entrycl>
</item>
<item>
<entrycl placeatentry="gruun">
</entrycl>
</item>
<item>
<entrycl placeatentry="blue">
</entrycl>
</item>
</items>
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="k1" match="entrycl" use="entry" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="entrycl[@placeatentry][not(key('k1', @placeatentry))]">
<xsl:copy>
<xsl:attribute name="new">yes</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<entrycl>
<entry>gruun</entry>
</entrycl>
</item>
<item>
<entrycl placeatentry="gruun"/>
</item>
<item>
<entrycl new="yes" placeatentry="blue"/>
</item>
</items>
Note that the search for a matching value in entry
includes the current entrycl
.