【问题标题】:Tokenize on each character in a string results in an error对字符串中的每个字符进行标记会导致错误
【发布时间】:2015-06-17 01:43:11
【问题描述】:

我正在尝试解决 Word 的 Office Open XML 中自定义 XML 丢失的问题,但我遇到了一些障碍。

我正在研究一种方法来跟踪对共享课程计划存储库的贡献,该存储库将驻留在 Omeka 站点中。我想要做的是将每个字符包装在书签中,然后在 Word 中打开文件时将其隐藏起来。这样一来,在异地复制和粘贴内容时,token 将进行传递,然后在再次上传新文件时重新连接到原始贡献者。

为此,我的 XML 当前如下所示:

<w:p w:rsidR="00196751" w:rsidRDefault="00956712">
    <w:r>
        <w:t>Some sample text.</w:t>
    </w:r>
    <w:bookmarkStart w:id="0" w:name="_GoBack"/>
    <w:bookmarkEnd w:id="0"/>
</w:p>

我需要它做的是这样的:

<w:p w:rsidR="00196751" w:rsidRDefault="00956712">
            <w:bookmarkStart w:id="0" w:name="_NAME_0001_20150616_1"/>
            <w:r>
                <w:t>S</w:t>
            </w:r>
            <w:bookmarkStart w:id="1" w:name="_NAME_0001_20150616_2"/>
            <w:bookmarkEnd w:id="0"/>
            <w:r>
                <w:t>o</w:t>
            </w:r>
            <w:bookmarkStart w:id="2" w:name="_NAME_0001_20150616_3"/>
            <w:bookmarkEnd w:id="1"/>
            <w:r>
                <w:t>m</w:t>
            </w:r>
            <w:bookmarkStart w:id="3" w:name="_NAME_0001_20150616_4"/>
            <w:bookmarkEnd w:id="2"/>
            <w:r>
                <w:t>e</w:t>
            </w:r>
            <w:bookmarkStart w:id="4" w:name="_NAME_0001_20150616_5"/>
            <w:bookmarkEnd w:id="3"/>
            <w:r>
                <w:t xml:space="preserve"> </w:t>
            </w:r>
[...]
<w:bookmarkStart w:id="17" w:name="_GoBack"/>
<w:bookmarkEnd w:id="16"/>
<w:bookmarkEnd w:id="17"/>
</w:p>

在我看来,我需要做的是在原始 w:t 项目上运行 tokenize 函数,所以我首先编写了以下 xslt:

<xsl:template match="w:t">
    <xsl:value-of select="tokenize(., '.??')"/>
</xsl:template>

但是,当我这样做时,我会收到一条错误消息。我的假设是,这是因为函数没有实际的模式来标记化,因为我要求它在每个字符上分开。有没有办法使用 tokenize 函数来做到这一点?如果是这样,我该怎么做才能得到我需要的结果?谢谢!

【问题讨论】:

  • 您没有想到我们可能想知道错误消息是什么?

标签: xml xslt xquery openxml


【解决方案1】:

您应该有一个模板,您可以将其应用于您的原始&lt;w:t&gt; 值:

<xsl:template name="tokenize">
    <xsl:param name="text"/>
    <xsl:choose>
        <xsl:when test="string-length($text) = 1">
            <w:r>
                <w:t><xsl:value-of select="$text"/></w:t>
            </w:r>
        </xsl:when>
        <xsl:otherwise>            
            <w:r>
                <w:t><xsl:value-of select="substring($text, 1, 1)"/></w:t>
            </w:r>
            <xsl:call-template name="tokenize">
                <xsl:with-param name="text" select="substring($text, 2, string-length($text)-1)"/>
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

不确定 w:bookmarkStart 和 w:bookmarkEnd 逻辑是如何工作的,但您可能可以从中弄清楚。

【讨论】:

    【解决方案2】:

    我可以想象您会遇到两个错误(很遗憾您没有想到告诉我们错误消息)。一是 tokenize 功能不可用,这意味着您使用的是 XSLT 1.0 处理器;另一个是你的正则表达式无效。

    如果您使用的是 XSLT 2.0 处理器,那么您可以使用 string-to-codepoints() 将字符串拆分为字符(并且您可以使用 codepoints-to-string() 将每个字符转回字符串)。

    如果您使用的是 XSLT 1.0 处理器,那么您需要使用 @yarivt 建议的递归模板“手动”进行拆分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多