xml - 使用 XSLT 根据 XML 中的文本拆分元素

标签 xml xslt-2.0

我正在使用 XSLT 将一个 XML 文件转换为另一个 XML 文件。 XML 文件具有如下元素:

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

现在,当我生成如下所示的新 XML 文件时,XSLT 中是否有任何方法:

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

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

提前谢谢您。

最佳答案

这是一种可能的 XSLT2 解决方案,它基于特定于 Description 元素的模板中的身份转换和 tokenize 字符串函数。

总体思路是首先将描述字符串拆分为“,”,然后将每个结果子字符串拆分为“:”,仅选择最后一部分。

<?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>

最后一步调用标准化空间函数,以去除前导/尾随空格;如果没有必要,请忽略该部分。

买者自负:这里假设描述文本的格式是固定的(即部门和学院始终以相同的顺序出现。)此外,假设描述元素中既不出现“:”也不出现“,”文本。

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

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

请注意,在一段纯文本中包含结构化信息并不完全是充分利用 XML,XML 完全与结构有关,但我猜格式不是您可以控制的。

根据评论更新:

基于regular expression的更强大的替代解决方案下面列出了匹配。在这种情况下,只有与 Department、Faculty 模式匹配的 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 regular expression 进行测试如果找到预期的模式,并捕获这种情况下的相应值。如果未找到匹配项,则复制 Description 元素的原始内容。

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

关于xml - 使用 XSLT 根据 XML 中的文本拆分元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14528240/

相关文章:

XSLT xsl :sequence. 它有什么用..?

xml - 从单个节点中的属性构建 XML 结构

java - 移除 ns2 作为默认命名空间前缀

java - 如何使线性布局出现在 GridView 中?

php - 如何在codeigniter中生成xml

xml - 如何在 XSLT 中获取行号?

ios - 在 swift 中检查 xml 元素是否为空的 EXC_BAD_INSTRUCTION 错误

php - 如何将 SOAP 响应转换为 XML 或 JSON 格式?

java - 如何在 XSLT 2.0 中获取当前 xml 文件名?

xslt - 如何将文档的内容打印到调试输出?