xmlxpathxsltxslt-2.0xpath-2.0

Substring-after value validate wtith another tag value format


My XML is below

<root>
<art-id p-type="main">XX.1108/ABCDE-01-2000-2000</art-id>
    <f id="F_ABCDE-01-2000-2000001" orientation="portrait">
            <label>F 1</label>
            <caption>
                <p>xxxx</p>
            </caption>
        </f>
        <f id="F_ABCDE-01-2000-2000002" orientation="portrait">
            <label>F 2</label>
            <caption>
                <p>YYYY</p>
            </caption>
        </f>
        <f id="F_ABCDE-01-2000-2000003" orientation="portrait">
            <label>F 3</label>
            <caption>
                <p>ZZZZ</p>
            </caption>
        </f>
</root>

My XSL is

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:mml="http://www.w3.org/1998/Math/MathML"
                xmlns:saxon="http://saxon.sf.net/" xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:func="http://exslt.org/functions"
                extension-element-prefixes="saxon" version='2.0'>
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:template name="FG-F-001">
        <xsl:for-each select="descendant::*:f">
            <xsl:variable name="xxx" select="substring-after(//*:article-id[@pub-id-type='doi'],'/')"/>
            <xsl:if test="not(matches(@id,'^F_') and matches(.,'{$xxx}'))">
                <message name="{name()}">“f” tag attribute “id” value must be in the format "F_[main suffix][nnn]".
                </message>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
    </xsl:stylesheet>

I want to validate "f" tag "id" attribute value against "art-id". The value in "f" tag should be in format "F_[main tag suffix after / symbol value ][nnn]" (ie: F_ABCDE-01-2000-2000001).


Solution

  • Somehow along the lines of

      <xsl:template match="f[not(matches(@id, '^F_' || ../art-id/substring-after(., '/') || '[0-9]{3}$'))]">
        <error f="{label}"/>
      </xsl:template>
    

    XPath 3.1 slipped in so if you are stuck with XPath 2.0 use e.g.

      <xsl:template match="f[not(matches(@id, concat('^F_', ../art-id/substring-after(., '/'), '[0-9]{3}$')))]">
        <error f="{label}"/>
      </xsl:template>