如何用XSLT 1.0从带occ属性的非结构化XML提取关联数据
使用XSLT 1.0实现动态关联I3/I4字段并生成指定输出格式
当然可以用XSLT 1.0搞定这个需求!针对你提到的非结构化XML中I3和I4字段通过occ属性关联的场景,我们可以借助XSLT的<key>机制来实现动态匹配,完全不用依赖固定的occ值顺序。
核心思路
- 先定义一个索引键,把所有
tag="I4"的<field>元素按它们的occ属性值分组,这样后续能快速通过occ值找到对应的类型描述。 - 遍历所有
tag="I3"的<field>元素,对每个元素,通过刚才定义的键找到同occ值的I4元素,用I4的文本内容作为<variable>的name属性,I3的文本内容作为<variable>的节点值。 - 最后把所有生成的
<variable>包裹在<output>根元素中。
完整XSLT 1.0示例代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 定义key:以I4元素的occ属性为键,关联对应的I4节点 --> <xsl:key name="i4-by-occ" match="field[@tag='I4']" use="@occ"/> <xsl:template match="/"> <output> <!-- 遍历所有tag为I3的field元素 --> <xsl:for-each select="//field[@tag='I3']"> <xsl:variable name="current-occ" select="@occ"/> <!-- 找到对应occ的I4元素,如果存在则获取其文本,否则用默认值 --> <xsl:variable name="var-name" select="key('i4-by-occ', $current-occ)/text()"/> <variable> <!-- 给name属性赋值:如果I4存在则用它的文本,否则用默认占位符 --> <xsl:attribute name="name"> <xsl:choose> <xsl:when test="$var-name"> <xsl:value-of select="$var-name"/> </xsl:when> <xsl:otherwise> <xsl:text>unknown_field_</xsl:text> <xsl:value-of select="$current-occ"/> </xsl:otherwise> </xsl:choose> </xsl:attribute> <!-- 输出I3的实际值 --> <xsl:value-of select="text()"/> </variable> </xsl:for-each> </output> </xsl:template> </xsl:stylesheet>
代码细节说明
<key>的作用:key('i4-by-occ', $current-occ)会直接返回所有occ属性等于当前I3元素occ值的I4元素,完美解决了occ顺序不固定、结构非结构化的问题。- 边界情况处理:加入了
<xsl:choose>逻辑,当某个I3没有对应I4时,会生成带占位符的name属性,避免出现空属性的情况,你可以根据实际需求修改占位符的格式。 - 动态遍历适配:通过
//field[@tag='I3']遍历所有I3元素,不管它们在XML结构中的层级位置,完全适配非结构化的输入。
示例输入输出
假设你的输入XML是这样的:
<root> <field tag="I4" occ="1">ProductName</field> <field tag="I3" occ="1">Laptop Pro</field> <field tag="I4" occ="3">Price</field> <field tag="I3" occ="2">2024-05-20</field> <field tag="I3" occ="3">$999</field> </root>
运行上面的XSLT后,输出会是:
<output> <variable name="ProductName">Laptop Pro</variable> <variable name="unknown_field_2">2024-05-20</variable> <variable name="Price">$999</variable> </output>
这个方案完全适配你提到的occ顺序变化、类型标签存在与否不确定的场景,用XSLT 1.0就能完美实现。
内容的提问来源于stack exchange,提问作者Fredrik Andersson
相关产品推荐
相关产品推荐

