Xml 是否可以创建一个变量,该变量也可以用于XSLT 3.0中的其他不同模板?

Xml 是否可以创建一个变量,该变量也可以用于XSLT 3.0中的其他不同模板?,xml,xslt,Xml,Xslt,我已经开始研究XSLT3.0中的主要变化。据我所知,在XSLT2.0中,我们无法创建在不同模板中使用的全局变量 使用XLST 3.0中的流模式和xsl:iterate函数或高阶函数或其他一些功能,我们现在能够“记住”以前函数中的值,因此,我们可以在不同的位置反复使用这些值 我的问题基于这个基本的例子: <?xml version="1.0" encoding="UTF-8"?> <PERSONAE PLAY="OTHELLO"> <TITLE>Dra

我已经开始研究XSLT3.0中的主要变化。据我所知,在XSLT2.0中,我们无法创建在不同模板中使用的全局变量

使用XLST 3.0中的流模式和xsl:iterate函数或高阶函数或其他一些功能,我们现在能够“记住”以前函数中的值,因此,我们可以在不同的位置反复使用这些值

我的问题基于这个基本的例子:

 <?xml version="1.0" encoding="UTF-8"?>
<PERSONAE PLAY="OTHELLO">
    <TITLE>Dramatis Personae</TITLE>
    <PERSON>
        <NAME>DUKE OF VENICE</NAME>
        <ID>123456</ID>
        <PROPERTIES>
            <BIRTHDAY>10.10.1980</BIRTHDAY>
            <CITY>New York</CITY>
            <COUNTRY>US</COUNTRY>
        </PROPERTIES>
    </PERSON>
    <PERSON>
        <NAME>BRABANTIO, a senator.</NAME>
        <ID>123456</ID>
        <PROPERTIES>
            <BIRTHDAY>10.10.1980</BIRTHDAY>
            <CITY>New York</CITY>
            <COUNTRY>US</COUNTRY>
        </PROPERTIES>
    </PERSON>
    <PERSON>
        <NAME>Other Senators.</NAME>
        <ID>123456</ID>
        <PROPERTIES>
            <BIRTHDAY>10.10.1980</BIRTHDAY>
            <CITY>New York</CITY>
            <COUNTRY>US</COUNTRY>
        </PROPERTIES>
    </PERSON>
</PERSONAE>

人物剧
威尼斯公爵
123456
10.10.1980
纽约
美国
布拉班蒂奥,参议员。
123456
10.10.1980
纽约
美国
其他参议员。
123456
10.10.1980
纽约
美国
假设这是我的xml示例,我想用java:util函数生成的唯一ID来更改这个值

XSLT是:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:util="java:java.util.UUID"
  version="3.0" expand-text="yes">

  <xsl:strip-space elements="PERSONAE"/>
  <xsl:template match="/">

    <xsl:apply-templates/>
    <xsl:call-template name="birthdayTemplate"/>
  </xsl:template>
  <xsl:template match="PERSONAE">
    <html>
      <head>
        <title>The Cast of {@PLAY}</title>
      </head>
      <body>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="TITLE">
    <h1>{.}</h1>
  </xsl:template>

  <xsl:template match="PERSON/NAME[count(tokenize(., ',') = 2)]">
    <p><b>{substring-before(., ',')}</b>: {substring-after(., ',')}</p>
  </xsl:template>

  <xsl:template match="PERSON/NAME">
    <p>
      <b>{.}</b>
    </p>
  </xsl:template>
  <xsl:template match="PERSON/ID">

    <p>
      <xsl:value-of select="util:toString(util:randomUUID())"/>
    </p>

  </xsl:template>
  <xsl:template match="PERSON/PROPERTIES"></xsl:template>
<xsl:template name="birthdayTemplate">

  <xsl:for-each select="PERSON/PROPERTIES">
      <PROPERTIES>
        <ID>THE UUID VALUE THAT IS CREATED IN THE RESULT DOCUMENT</ID>
      </PROPERTIES>
  </xsl:for-each>
</xsl:template>


</xsl:stylesheet>

{@PLAY}的演员阵容
{.}
{substring before(,',')}:{substring before(,,',')}

{.}

在结果文档中创建的UUID值
我希望得到的结果是:

<html xmlns:util="java:java.util.UUID">
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>The Cast of OTHELLO</title>
   </head>
   <body>
      <h1>Dramatis Personae</h1>

      <p><b>DUKE OF VENICE</b></p>

      <p>a6759c7b-ff13-4b27-b726-ecd6ebaea96c</p>



      <p><b>BRABANTIO, a senator.</b></p>

      <p>1a58c699-ee9e-4093-8224-5319127fbf8c</p>



      <p><b>Other Senators.</b></p>

      <p>482908c6-2437-406d-a421-c7d2a103aba7</p>


      <p>
         <PROPERTIES>
            <ID>a6759c7b-ff13-4b27-b726-ecd6ebaea96c</ID>
            <BIRTHDAY>10.10.1980</BIRTHDAY>
            <CITY>New York</CITY>
            <COUNTRY>US</COUNTRY>
         </PROPERTIES>
      </p>
      <p>
         <PROPERTIES>
            <ID>1a58c699-ee9e-4093-8224-5319127fbf8c</ID>
            <BIRTHDAY>10.10.1980</BIRTHDAY>
            <CITY>New York</CITY>
            <COUNTRY>US</COUNTRY>
         </PROPERTIES>
      </p>
      <p>
         <PROPERTIES>
            <ID>482908c6-2437-406d-a421-c7d2a103aba7</ID>
            <BIRTHDAY>10.10.1980</BIRTHDAY>
            <CITY>New York</CITY>
            <COUNTRY>US</COUNTRY>
         </PROPERTIES>
      </p>
   </body>
</html>

奥赛罗的演员阵容
人物剧
威尼斯公爵

a6759c7b-ff13-4b27-b726-ecd6ebaea96c

布拉班蒂奥,参议员

1a58c699-ee9e-4093-8224-5319127fbf8c

其他参议员

482908c6-2437-406d-a421-c7d2a103aba7

a6759c7b-ff13-4b27-b726-ecd6ebaea96c 10.10.1980 纽约 美国

1a58c699-ee9e-4093-8224-5319127fbf8c 10.10.1980 纽约 美国

482908c6-2437-406d-a421-c7d2a103aba7 10.10.1980 纽约 美国

从xml示例中可以看到,PERSON节点的ID是相同的,为了解决这个问题,我决定使用随机uuid生成器为所有PERSON节点分配不同的ID,因此可以唯一地标识它们

我的另一个意图是为PERSON节点的不同属性创建另一个模板,并使用相同的唯一ID连接这些属性

问题是:在XSLT 3.0中(或者如果XSLT 2.0中有,但优先级是3.0),有没有办法在显示这些随机uuid之前读取它们(或者我不知道如何处理它),并在递归匹配的不同位置使用相同的值


编辑:我通过创建另一个XSLT转换修复了这个问题,该转换只使用随机UUID更改值,然后在第二个转换中复制值。如果使用XSLT 3.0和streamable模式在一次转换中就可以实现呢?或还是别的什么?我理解你的答案@Tomalak,但我只是想知道是否有其他方法可以解决这个问题

您可以使用如下定义的全局

<xsl:variable name="idrefs">
  <xsl:for-each select="//PERSON">
      <PERSON newid="id_{position()}">
          <ID>{generate-id(ID)}</ID>
      </PERSON>
  </xsl:for-each>
</xsl:variable>
您可以像这样获得新id(假设您位于旧id节点上)


试试这个XSLT

<xsl:stylesheet
  version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:util="java:java.util.UUID"
  expand-text="yes">
  <xsl:strip-space elements="PERSONAE"/>

  <xsl:variable name="idrefs">
      <xsl:for-each select="//PERSON">
          <PERSON newid="id_{position()}">
              <ID>{generate-id(ID)}</ID>
          </PERSON>
      </xsl:for-each>
  </xsl:variable>

  <xsl:key name="idrefs" match="PERSON" use="ID" />

  <xsl:template match="/">
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="PERSONAE">
    <html>
      <head>
        <title>The Cast of {@PLAY}</title>
      </head>
      <body>
        <xsl:apply-templates/>
        <xsl:call-template name="birthdayTemplate"/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="TITLE">
    <h1>{.}</h1>
  </xsl:template>

  <xsl:template match="PERSON/NAME[count(tokenize(., ',') = 2)]">
    <p><b>{substring-before(., ',')}</b>: {substring-after(., ',')}</p>
  </xsl:template>

  <xsl:template match="PERSON/NAME">
    <p>
      <b>{.}</b>
    </p>
  </xsl:template>

  <xsl:template match="PERSON/ID">
    <p>
      <xsl:value-of select="key('idrefs', generate-id(), $idrefs)/@newid"/>
    </p>
  </xsl:template>

  <xsl:template match="PERSON/PROPERTIES"></xsl:template>

  <xsl:template name="birthdayTemplate">
    <xsl:for-each select="PERSON/PROPERTIES">
      <PROPERTIES>
        <ID>{key('idrefs', generate-id(../ID), $idrefs)/@newid}</ID>
        <xsl:copy-of select="*" />
      </PROPERTIES>
    </xsl:for-each>
  </xsl:template>    
</xsl:stylesheet>

{生成id(id)}
{@PLAY}的演员阵容
{.}
{substring before(,',')}:{substring before(,,',')}

{.}

{key('idrefs',generate id(../id),$idrefs)/@newid}
您可以使用如下定义的全局

<xsl:variable name="idrefs">
  <xsl:for-each select="//PERSON">
      <PERSON newid="id_{position()}">
          <ID>{generate-id(ID)}</ID>
      </PERSON>
  </xsl:for-each>
</xsl:variable>
您可以像这样获得新id(假设您位于旧id节点上)


试试这个XSLT

<xsl:stylesheet
  version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:util="java:java.util.UUID"
  expand-text="yes">
  <xsl:strip-space elements="PERSONAE"/>

  <xsl:variable name="idrefs">
      <xsl:for-each select="//PERSON">
          <PERSON newid="id_{position()}">
              <ID>{generate-id(ID)}</ID>
          </PERSON>
      </xsl:for-each>
  </xsl:variable>

  <xsl:key name="idrefs" match="PERSON" use="ID" />

  <xsl:template match="/">
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="PERSONAE">
    <html>
      <head>
        <title>The Cast of {@PLAY}</title>
      </head>
      <body>
        <xsl:apply-templates/>
        <xsl:call-template name="birthdayTemplate"/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="TITLE">
    <h1>{.}</h1>
  </xsl:template>

  <xsl:template match="PERSON/NAME[count(tokenize(., ',') = 2)]">
    <p><b>{substring-before(., ',')}</b>: {substring-after(., ',')}</p>
  </xsl:template>

  <xsl:template match="PERSON/NAME">
    <p>
      <b>{.}</b>
    </p>
  </xsl:template>

  <xsl:template match="PERSON/ID">
    <p>
      <xsl:value-of select="key('idrefs', generate-id(), $idrefs)/@newid"/>
    </p>
  </xsl:template>

  <xsl:template match="PERSON/PROPERTIES"></xsl:template>

  <xsl:template name="birthdayTemplate">
    <xsl:for-each select="PERSON/PROPERTIES">
      <PROPERTIES>
        <ID>{key('idrefs', generate-id(../ID), $idrefs)/@newid}</ID>
        <xsl:copy-of select="*" />
      </PROPERTIES>
    </xsl:for-each>
  </xsl:template>    
</xsl:stylesheet>

{生成id(id)}
{@PLAY}的演员阵容
{.}
{substring before(,',')}:{substring before(,,',')}

{.}

{key('idrefs',generate id(../id),$idrefs)/@newid}
这些例子中的真正问题是副作用。函数
util:randomUUID()
不是一个纯函数,因为它每次都返回不同的值。无论您使用的是XSLT1.0、2.0还是3.0,对这些函数的调用都非常依赖于实现


XSLT3.0为您提供了一些额外的工具来帮助解决这个问题。有一个
fn:random-number-generator()
,它使您能够用纯函数方法生成随机数。用户定义函数上还有注释(
cache=yes/no
new each time=yes/no/maybe
),允许您向处理器指示如何处理同一函数上的重复调用。但当您开始调用具有副作用的外部方法时,语言的语义仍然是模糊的。

这些示例中的真正问题是副作用。函数
util:randomUUID()
不是一个纯函数,因为它每次都返回不同的值。无论您使用的是XSLT1.0、2.0还是3.0,对这些函数的调用都非常依赖于实现

XSLT3.0为您提供了一些额外的工具来帮助解决这个问题。有一个
fn:random-number-generator()
,它使您能够以纯函数的方式生成随机数