2

我正在使用 XSLT 将一个 XML 文件转换为另一个 XML 文件。XML 文件有这样的元素:

<Course>
      <ID>1001</ID>
      <Seats>10</Seats>
      <Description>Department: CS , Faculty: XYZ</Description>
</Course>

现在在 XSLT 中有什么方法可以让我生成如下所示的新 XML 文件:

<Course>
      <ID>1001</ID>
      <Seats>10</Seats>
      <Department> CS </Department> 
      <Faculty> XYZ</Faculty>
</Course>

也就是说,我想将Description元素拆分为两个不同的元素DepartmentFaculty,它们基本上是用逗号分隔的内容。我使用 XMLspy 来编写我的 XSLT。

先感谢您。

4

1 回答 1

2

这是一个可能的 XSLT2 解决方案,它基于特定于 Description 元素的模板中的标识转换和标记化字符串函数。

一般的想法是首先在“,”上拆分描述字符串,然后在“:”上拆分每个结果子字符串,只选择最后一部分。

<?xml version="1.0"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions">

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Description">
        <xsl:variable name="tokens" select="fn:tokenize(text(),',')"/>
        <xsl:element name="Department"><xsl:value-of select="fn:normalize-space(fn:tokenize($tokens[1],':')[2])"/></xsl:element>
        <xsl:element name="Faculty"><xsl:value-of select="fn:normalize-space(fn:tokenize($tokens[2],':')[2])"/></xsl:element>
    </xsl:template>

</xsl:stylesheet>

normalize-space 函数作为最后一步调用,以去除前导/尾随空格;如果这不是必需的,请忽略这一点。

注意事项:这里的假设是描述文本的格式是固定的(即部门和学院总是以相同的顺序出现。)此外,假设在描述元素文本中既没有“:”也没有“,”。

上面的转换产生了预期的结果:

<?xml version="1.0" encoding="UTF-8"?><Course>
      <ID>1001</ID>
      <Seats>10</Seats>
      <Department>CS</Department>
      <Faculty>XYZ</Faculty>
</Course>

请注意,在纯文本运行中包含结构化信息不能充分利用 XML,这完全是关于结构的,但我猜这种格式不是您可以控制的。

根据评论更新:

下面列出了基于正则表达式匹配的更强大的替代解决方案。在这种情况下,只有与 Department、Faculty 模式匹配的 Description 元素被重写;否则原始 Description 元素将通过:

<?xml version="1.0"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions">

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Description">
        <xsl:analyze-string select="." regex="\s*Department:\s*(.+)\s*,\s*Faculty:\s*(.+)\s*">
            <xsl:matching-substring>
                <xsl:element name="Department"><xsl:value-of select="regex-group(1)"/></xsl:element>
                <xsl:element name="Faculty"><xsl:value-of select="regex-group(2)"/></xsl:element>
            </xsl:matching-substring>
            <xsl:non-matching-substring>
                <xsl:element name="Description"><xsl:copy/></xsl:element>
            </xsl:non-matching-substring>
        </xsl:analyze-string>
    </xsl:template>

</xsl:stylesheet>

这里的关键思想是xsl:analyze-string通过XSLT 正则表达式来测试是否找到了预期的模式,并在这种情况下捕获相应的值。如果未找到匹配项,则复制 Description 元素的原始内容。

注意:将其与根元素集成留给读者作为练习(因为 OP 示例未显示 Course 元素适合的位置)。

于 2013-01-25T19:37:28.207 回答