XML/XSLT stylesheet/function

Материал из Web эксперт
Перейти к: навигация, поиск

Define and use function

File: Data.xml
<?xml version="1.0"?>
<parts>
  <part id="p10" idref="p20"/>
  <part id="p20" idref="p30 p40"/>
  <part id="p30"/>
  <part id="p40" idref="p10"/>
</parts>
File: Transform.xml
<?xml version="1.0"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:graph="http://wrox.ru/569090/graph"
  xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
  <xsl:function name="graph:refers" as="xs:boolean">
    <xsl:param name="links" as="node()" />
    <xsl:param name="A" as="node()" />
    <xsl:param name="B" as="node()" />
    <xsl:variable name="direct" as="node()*">
      <xsl:apply-templates select="$links">
        <xsl:with-param name="from" select="$A" />
      </xsl:apply-templates>
    </xsl:variable>
    <xsl:sequence
      select="if (exists($direct intersect $B)) then true()
                         else if (some $C in $direct 
                                  satisfies graph:refers($links, $C, $B)) then true()
                         else false()" />
  </xsl:function>
</xsl:transform>



local function

File: Data.xml
<?xml version="1.0"?>
<SCENE>
  <TITLE>title 1</TITLE>
  <STAGEDIR>A</STAGEDIR>
  <SPEECH>
    <SPEAKER>B</SPEAKER>
    <LINE>C</LINE>
    <LINE>D</LINE>
    <LINE>E</LINE>
    <LINE>F</LINE>
  </SPEECH>
</SCENE>
File: Transform.xslt
<?xml version="1.0"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:local="local-functions.uri" exclude-result-prefixes="xs local"
  version="2.0">
  <xsl:variable name="speakers" as="xs:string*"
    select="for $w in distinct-values(//LINE)
                      return upper-case($w)" />
  <xsl:function name="local:split" as="xs:string*">
    <xsl:param name="line" as="xs:string" />
    <xsl:sequence select="tokenize($line, "\W")" />
  </xsl:function>
  <xsl:function name="local:is-character" as="xs:boolean">
    <xsl:param name="word" as="xs:string" />
    <xsl:sequence select="upper-case($word)=$speakers" />
  </xsl:function>
  <xsl:template name="scan-line">
    <xsl:param name="words" as="xs:string*" />
    <xsl:if test="count($words) ge 3">
      <xsl:if
        test="local:is-character($words[1]) and
                   lower-case($words[2]) = "and" and
                   local:is-character($words[3])">
          <xsl:value-of select="$words[position() = 1 to 3]"
            separator=" " />
      </xsl:if>
    </xsl:if>
  </xsl:template>
  <xsl:template match="/">
    <naming-lines>
      <xsl:for-each select="//LINE">
        <xsl:call-template name="scan-line">
          <xsl:with-param name="words"
            select="local:split(.)" />
        </xsl:call-template>
      </xsl:for-each>
    </naming-lines>
  </xsl:template>
</xsl:transform>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<naming-lines/>