4

我希望能够选择文档中某种类型的所有属性(例如,//@arch),然后获取该节点集并将值解析到第二个节点集中。当我说“解析”时,具体而言,我的意思是我想像这样打开一个节点集:

arch="value1;value2;value3"
arch="value1:value4"

进入这样的节点集:

arch="value1"
arch="value2"
arch="value3"
arch="value1"
arch="value4"

或类似的东西; 我想从属性中获取单个值并进入它们自己的节点。

如果我能把它弄到那个状态,我就有很多排序和删除重复的方法,之后我会使用完成的节点集来完成发布任务。

作为一种方法,我并不是在这里寻找一个整洁的答案。我知道 XSLT 不能做动态数组,但这与不能做动态数组或模仿功能的重要部分的事情不同。

我想到的一个想法是我可以计算第一个节点集中的节点和分隔符的数量,计算第二个节点集需要的条目数并(以某种方式)创建它,并使用子字符串函数将第一个节点集解析为第二个节点集。

通常有一种方法可以解决 XSLT 的问题。以前有没有人解决过这个问题?

感谢您的帮助,杰夫。

4

2 回答 2

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>
于 2013-08-20T15:56:38.567 回答
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>
于 2013-08-20T15:56:53.217 回答