常规 我正在尝试修改包含JavaScript的XML。如果JavaScript引用其中一个页面顶级,我想添加一个额外的顶级层次结构级别。
具体细节 我想找到新的顶级(formName),然后将它们添加到脚本中,如果它们具有以页面顶层(pageNames和subPageNames)开头的分配。我试图在XMLSpy中运行它,但我甚至无法填充变量formName。解决这个问题的最佳方法是什么?
我的示例XML:
<?xml version="1.0" encoding="UTF-8"?>
<template>
<subform name="formABC">
<pageSet>
<pageArea name="Page1">
<subform>
<field>
<event>
<script>this.rawValue = SubPageA.subhuvud.namn.rawValue;</script>
</event>
</field>
<field>
<event>
<script>this.rawValue = not_this.rawValue;</script>
</event>
</field>
</subform>
</pageArea>
<pageArea name="Page2">
<field>
<event>
<script>this.rawValue = SubPageK.subhuvud.namn.rawValue;</script>
</event>
</field>
<area>
<field>
<event>
<script>this.rawValue = Page1.subhuvud.namn.rawValue;</script>
</event>
</field>
<field>
<event>
<script>this.rawValue = other.rawValue;</script>
</event>
</field>
</area>
</pageArea>
</pageSet>
<subform name="SubPageA">
</subform>
<subform name="SubPageK">
</subform>
</subform>
</template>
我目前的XSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"
xmlns:xdp="http://ns.adobe.com/xdp/">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="formName" select="/xdp:xdp/template/subform/@name"/>
<xsl:variable name="pageNames" select="/xdp:xdp/template/subform/subform/@name"/>
<xsl:variable name="subPageNames" select="/xdp:xdp/template/subform/pageSet/pageArea/@name"/>
<xsl:variable name="allPageNames" select="concat($pageNames, $subPageNames)"/>
<!-- Identity rule.-->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!--Rewite Javascript-->
<!--Insert formname in front of page that is first.-->
<xsl:template match="//script">
<xsl:variable name="match" select="exsl:node-set($allPageNames)[contains(current(), .)]"/>
<xsl:choose>
<xsl:when test="$match"> <!--this.rawValue = Page1.subhuvud.namn.rawValue;-->
<xsl:value-of select="substring-before(., $match)"/> <!--this.rawValue = -->
<xsl:value-of select="$formName"/> <!--formABC-->
<xsl:value-of select="'.'"/> <!--.-->
<xsl:value-of select="$match"/> <!--Page1-->
<xsl:value-of select="substring-after(., $match)"/> <!--.subhuvud.namn.rawValue;-->
</xsl:when> <!--this.rawValue = formABC.Page1.subhuvud.namn.rawValue;-->
<xsl:otherwise>
<xsl:copy/>
<xsl:apply-templates select="node()|@*"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
我寻求的输出:
<?xml version="1.0" encoding="UTF-8"?>
<template>
<subform name="formABC">
<pageSet>
<pageArea name="Page1">
<subform>
<field>
<event>
<script>this.rawValue = formABC.SubPageA.subhuvud.namn.rawValue;</script>
</event>
</field>
<field>
<event>
<script>this.rawValue = not_this.rawValue;</script>
</event>
</field>
</subform>
</pageArea>
<pageArea name="Page2">
<field>
<event>
<script>this.rawValue = formABC.SubPageK.subhuvud.namn.rawValue;</script>
</event>
</field>
<area>
<field>
<event>
<script>this.rawValue = formABC.Page1.subhuvud.namn.rawValue;</script>
</event>
</field>
<field>
<event>
<script>this.rawValue = other.rawValue;</script>
</event>
</field>
</area>
</pageArea>
</pageSet>
<subform name="SubPageA">
</subform>
<subform name="SubPageK">
</subform>
</subform>
</template>
答案 0 :(得分:1)
关于绑定变量的值,我扩展了我的注释,指出以select
为根的/xdp:xdp
表达式永远不会匹配示例输入文件中的任何内容,因此关联变量的值将永远是空节点集。您应该能够通过删除该元素来解决该问题(关于示例输入):
<xsl:variable name="formName" select="/template/subform/@name"/>
接下来,我发现你为变量allPageNames
形成值的机制不起作用,因为concat()
需要 string 参数,但是你试图提供节点集。也不会将节点集转换为字符串做正确的事情,因为
XPath有一个节点集联合运算符|
,您可以在表达式中使用此变量的值。例如,
<xsl:variable name="pageNames" select="/template/subform/subform/@name"/>
<xsl:variable name="subPageNames" select="/template/subform/pageSet/pageArea/@name"/>
<xsl:variable name="allPageNames" select="$pageNames | $subPageNames"/>
现在你不需要EXSL(针对你在问题中提出的内容),因为allPageNames
已经是一个节点集。
但这还不够:match
模板中的变量script
存在问题。其赋值中的select
表达式将不起作用,因为contains()
是另一个字符串函数,并且您正在尝试将节点集传递给它。此外,在谓词内部,它将评估正在测试的节点 not ,因为它看起来你想要,正在转换<script>
元素。在任何情况下,您似乎试图执行的测试都容易出现误报。
我建议采用不同的方法。首先,确定要测试的对象的名称。当使用script
元素作为上下文节点进行处理时,这看起来可能与您描述的目标一致:
<xsl:variable name="topObject"
select="normalize-space(substring-before(concat(substring-after(., '='), '.'), '.'))"/>
完成此操作后,您可以测试所选名称是否属于$allPageNames
节点通过此测试表达式设置的名称:$allPageNames[. = $topObject]
。总的来说,script
模板可能如下所示:
<xsl:template match="script">
<!-- assumed: this element has text-only content -->
<xsl:variable name="topObject"
select="normalize-space(substring-before(concat(substring-after(., '='), '.'), '.'))"/>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:choose>
<xsl:when test="$allPageNames[. = $topObject]">
<xsl:value-of select="substring-before(., $topObject)"/>
<xsl:value-of select="$formName"/>
<xsl:text>.</xsl:text>
<xsl:value-of select="$topObject"/>
<xsl:value-of select="substring-after(., $topObject)"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="text()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>