Xml 是否可以创建一个变量,该变量也可以用于XSLT 3.0中的其他不同模板?
我已经开始研究XSLT3.0中的主要变化。据我所知,在XSLT2.0中,我们无法创建在不同模板中使用的全局变量 使用XLST 3.0中的流模式和xsl:iterate函数或高阶函数或其他一些功能,我们现在能够“记住”以前函数中的值,因此,我们可以在不同的位置反复使用这些值 我的问题基于这个基本的例子: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
<?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()
,它使您能够以纯函数的方式生成随机数