Xml XSLT中的字符串操作、多输入和递归

Xml XSLT中的字符串操作、多输入和递归,xml,xslt-2.0,Xml,Xslt 2.0,关于这个问题 我仍在使用一个优雅的函数来搜索特定的代码段,如果找到了某些触发器,则返回后面的子字符串,直到结束触发器。示例如下: <Data>Moby Dick [videorecording] / United Artists ; A Moulin Picture ; screenplay by Ray Bradbury and John Huston ; directed by John Huston.</Data> <Data>Oliv

关于这个问题

我仍在使用一个优雅的函数来搜索特定的代码段,如果找到了某些触发器,则返回后面的子字符串,直到结束触发器。示例如下:

    <Data>Moby Dick [videorecording] / United Artists ; A Moulin Picture ; screenplay by Ray Bradbury and John Huston ; directed by John Huston.</Data>

    <Data>Oliver Twist [videorecording] / Independent Producers ; screen play by David Lean and Stanley Haynes ; produced by Ronald Neame ; directed by David Lean.</Data>

    <Data>Romeo + Juliet [videorecording] / Twentieth Century Fox presents a Bazmark production ; producers, Gabriella Martinelli, Baz Luhrmann ; screenplay, Craig Pearce, Baz Luhrmann.</Data>
白鲸[录像]/United Artists;磨坊画;雷·布拉德伯里和约翰·休斯顿的剧本;导演约翰·休斯顿。
奥利弗·特维斯[录像]/独立制片人;大卫·莱恩和斯坦利·海恩斯的银幕剧;由罗纳德·尼姆制作;导演大卫·莱恩。
罗密欧+朱丽叶[录像]/二十世纪福克斯公司推出了一部巴兹马克的作品;制片人,加布里埃拉·马丁内利,巴兹·卢尔曼;剧本,克雷格·皮尔斯,巴兹·鲁尔曼。
预期结果:

...
<writer>Ray Bradbury</writer>
<writer>John Huston</writer>
...

...
<writer>David Lean</writer>
<writer>Stanley Haynes</writer>
...

...
<writer>Craig Pearce</writer>
<writer>Baz Luhrmann</writer>
...
。。。
雷·布拉德伯里
约翰·休斯顿
...
...
大卫·莱恩
斯坦利·海恩斯
...
...
克雷格·皮尔斯
巴兹·鲁尔曼
...
我的尝试:

 <xsl:function name="foo:personSep">
        <xsl:param name="string"/>
        <xsl:param name="delim"/>
        <xsl:choose>
            <xsl:when test="not(contains($string,$delim))">
                <writer>
                    <xsl:value-of select="$string"/>
                </writer>
            </xsl:when>
            <xsl:when test="contains($string,$delim)">
                <writer>
                    <xsl:value-of select="substring-before($string, $delim)"/>
                </writer>
                <xsl:sequence select="functx:personSep(substring-after($string, $delim), $delim)"/>
            </xsl:when>
            <xsl:otherwise>
                <writer> 
                </writer>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:function>

    <xsl:template match="ss:Cell[3]/ss:Data" mode="writer">
        <xsl:variable name="cell3Data" select="normalize-space(.)"/>

        <xsl:variable name="writerFind" as="xs:string*"
            select="('screenplay by ','screen play by ','screenplay, ')"/>

        <xsl:for-each select="1 to count($writerFind)">
            <xsl:variable name="x" select="."/>
            <xsl:variable name="writer" select="substring-after($cell3Data, $writerFind[$x])"/>
            <xsl:if test="$writer != ''">
                <xsl:if test="contains($writer, ' and ')">
                    <xsl:sequence
                        select="foo:personSep(functx:right-trim(replace($writer, '[;\.].*$', '')),' and ')"
                    />
                </xsl:if>
                <xsl:if test="contains($writer, ', ')">
                    <xsl:sequence
                        select="foo:personSep(functx:right-trim(replace($writer, '[;\.].*$', '')),', ')"
                    />
                </xsl:if>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>

我的boot-strappy-kludgeriffic版本基本上可以正常工作,但我确信有一个更精简、更干净的解决方案……而且它不会捕获任何包含逗号和an之类的版本


“screen play by,John Smith,Ed Jones和Robert Danvers”

以下是一个模板,用于匹配
数据和提取
编写器:

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"    
    version="2.0">

<xsl:output method="xml" indent="yes"/>

<xsl:template match="Data">
  <xsl:analyze-string select="." regex="(screenplay by |screen play by |screenplay, )([^.;]+)(;|\.|$)">
    <xsl:matching-substring>
      <xsl:analyze-string select="regex-group(2)" regex="(\w+(\s*\w*))(\s*(,|and|$))">
        <xsl:matching-substring>
          <writer><xsl:value-of select="normalize-space(regex-group(1))"/></writer>
        </xsl:matching-substring>
      </xsl:analyze-string>
    </xsl:matching-substring>
  </xsl:analyze-string>
</xsl:template>

</xsl:stylesheet>

当我在输入端应用Saxon 9.5时

<Root>
   <Data>Moby Dick [videorecording] / United Artists ; A Moulin Picture ; screenplay by Ray Bradbury and John Huston ; directed by John Huston.</Data>

    <Data>Oliver Twist [videorecording] / Independent Producers ; screen play by David Lean and Stanley Haynes ; produced by Ronald Neame ; directed by David Lean.</Data>

    <Data>Romeo + Juliet [videorecording] / Twentieth Century Fox presents a Bazmark production ; producers, Gabriella Martinelli, Baz Luhrmann ; screenplay, Craig Pearce, Baz Luhrmann.</Data>
</Root>

白鲸[录像]/联合艺术家;磨坊画;雷·布拉德伯里和约翰·休斯顿的剧本;导演约翰·休斯顿。
奥利弗·特维斯[录像]/独立制片人;大卫·莱恩和斯坦利·海恩斯的银幕剧;由罗纳德·尼姆制作;导演大卫·莱恩。
罗密欧+朱丽叶[录像]/二十世纪福克斯公司推出了一部巴兹马克的作品;制片人,加布里埃拉·马丁内利,巴兹·卢尔曼;剧本,克雷格·皮尔斯,巴兹·鲁尔曼。
我得到了结果

   <writer>Ray Bradbury</writer>
<writer>John Huston</writer>

    <writer>David Lean</writer>
<writer>Stanley Haynes</writer>

    <writer>Craig Pearce</writer>
<writer>Baz Luhrmann</writer>
雷·布拉德伯里 约翰·休斯顿 大卫·莱恩 斯坦利·海恩斯 克雷格·皮尔斯 巴兹·鲁尔曼
如果你想写一个函数,那么就做

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="xs mf"    
    version="2.0">

<xsl:output method="xml" indent="yes"/>

<xsl:function name="mf:extract" as="element()*">
  <xsl:param name="input" as="xs:string"/>
  <xsl:param name="markers" as="xs:string*"/>
  <xsl:param name="element-name" as="xs:string"/>
  <xsl:analyze-string select="$input" regex="({string-join($markers, '|')})([^.;]+)(;|\.|$)">
    <xsl:matching-substring>
      <xsl:analyze-string select="regex-group(2)" regex="(\w+(\s*\w*))(\s*(,|and|$))">
        <xsl:matching-substring>
          <xsl:element name="{$element-name}"><xsl:value-of select="normalize-space(regex-group(1))"/></xsl:element>
        </xsl:matching-substring>
      </xsl:analyze-string>
    </xsl:matching-substring>
  </xsl:analyze-string>
</xsl:function>

<xsl:template match="Data">
  <xsl:sequence select="mf:extract(., ('screenplay by ', 'screen play by ', 'screenplay, '), 'writer')"/>
</xsl:template>

</xsl:stylesheet>


XSLT2.0中的问题似乎最好通过
分析字符串和捕获数据的适当正则表达式模式来解决。太棒了!谢谢你,马丁!特别是对于添加函数部分,因为我想搜索几个元素(导演、演员等),这样就可以更精简地拥有一个函数并只传递角色的值