我希望能够选择文档中某种类型的所有属性(例如// @ arch),然后获取该节点集并将值解析为第二个节点集。当我说“解析”时,具体我的意思是我想要转换这样的节点:
arch="value1;value2;value3"
arch="value1:value4"
进入这样的节点集:
arch="value1"
arch="value2"
arch="value3"
arch="value1"
arch="value4"
或类似的东西;我想从属性中获取各个值并将其放入自己的节点中。
如果我可以进入该状态,我有很多方法可以进行排序和重复删除,之后我将使用完成的节点集进行发布任务。
作为一种方法,我并不是在寻找一个整洁的答案。我知道XSLT不能做动态数组,但这与不能做之类的动态数组或模仿功能重要部分的东西不同。
我想到的一个想法是,我可以计算第一个节点集中的节点和分隔符的数量,计算第二个节点集所需的条目数并创建它(以某种方式),并使用substring函数用于解析第一个节点集到第二个节点集。
通常有办法解决XSLT的问题;有没有人在此之前解决过这个问题?
感谢您的帮助, 杰夫。
答案 0 :(得分:2)
您可以使用tokenize
表达式中的for
函数来获取单独值的序列,然后为每个值创建一个属性节点。但是,由于XSLT不允许您创建没有父元素的裸属性节点,因此您必须使用这样的技巧:
<xsl:variable name="archElements">
<xsl:for-each select="for $attr in $initialNodeSet
return tokenize($attr, '[:;]')">
<dummy arch="{.}" />
</xsl:for-each>
</xsl:variable>
然后$archElements/dummy/@arch
应该是您需要的一组独立的arch
属性节点。
完整示例:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes" />
<xsl:template match="/">
<xsl:variable name="inputData">
<a arch="value1;value2;value3" />
<a arch="value1:value4" />
</xsl:variable>
<!-- create an example node set containing the two arch attribute nodes -->
<xsl:variable name="initialNodeSet" select="$inputData/a/@arch" />
<!-- tokenize and generate one arch attribute node for each value -->
<xsl:variable name="archElements">
<xsl:for-each select="for $attr in $initialNodeSet
return tokenize($attr, '[:;]')">
<dummy arch="{.}" />
</xsl:for-each>
</xsl:variable>
<!-- output to verify -->
<r>
<xsl:for-each select="$archElements/dummy/@arch">
<c><xsl:copy-of select="."/></c>
</xsl:for-each>
</r>
</xsl:template>
</xsl:stylesheet>
当在任何输入文档上运行时(内容被忽略),这会产生
<?xml version="1.0" encoding="UTF-8"?>
<r>
<c arch="value1"/>
<c arch="value2"/>
<c arch="value3"/>
<c arch="value1"/>
<c arch="value4"/>
</r>
答案 1 :(得分:2)
我认为你要找的是一个序列。序列可以是节点或原子值(参见http://www.w3.org/TR/xslt20/#constructing-sequences)。
这是一个示例,显示序列的构造,然后迭代它。序列是来自@arch
的原子值,但它也可以是节点。
XML输入
<doc>
<foo arch="value1;value2;value3"/>
<foo arch="value1:value4"/>
</doc>
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="archSequence" as="item()*">
<xsl:for-each select="//@arch">
<xsl:for-each select="tokenize(.,'[;:]')">
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/*">
<sequence>
<xsl:for-each select="$archSequence">
<item><xsl:value-of select="."/></item>
</xsl:for-each>
</sequence>
</xsl:template>
</xsl:stylesheet>
XML输出
<sequence>
<item>value1</item>
<item>value2</item>
<item>value3</item>
<item>value1</item>
<item>value4</item>
</sequence>
元素序列的示例(相同的输出):
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="archSequence" as="element()*">
<xsl:for-each select="//@arch">
<xsl:for-each select="tokenize(.,'[;:]')">
<item><xsl:value-of select="."/></item>
</xsl:for-each>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/*">
<sequence>
<xsl:for-each select="$archSequence">
<xsl:copy-of select="."/>
</xsl:for-each>
</sequence>
</xsl:template>
</xsl:stylesheet>