You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于属性值匹配提取节点值的XSLT转换求助

解决XSLT中基于属性匹配提取节点值的问题

看了你提供的示例XML、期望输出和尝试的XSLT代码,能发现你现在的代码存在几个关键问题:比如定义了重复的match="/"模板(XSLT里同一匹配模式只能有一个有效模板),key的使用逻辑没对应上需求,而且没有聚焦到核心的<field>元素处理上。

下面是针对你需求的完整解决方案:

正确的XSLT代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
    <!-- 定义key,通过identifier快速查找category -->
    <xsl:key name="category-by-id" match="category" use="@identifier"/>
    <!-- 定义key,通过identifier快速查找field-type -->
    <xsl:key name="fieldtype-by-id" match="field-type" use="@identifier"/>
    
    <!-- 匹配根节点,直接处理所有field元素 -->
    <xsl:template match="/">
        <xsl:apply-templates select="root/custom/field"/>
    </xsl:template>
    
    <!-- 处理每个field元素 -->
    <xsl:template match="field">
        <field identifier="{@identifier}">
            <!-- 保留原有的name和description -->
            <xsl:copy-of select="name | description"/>
            
            <!-- 添加category-ref-name:通过category-ref找到对应的category的name -->
            <category-ref-name>
                <xsl:value-of select="key('category-by-id', @category-ref)/name"/>
            </category-ref-name>
            
            <!-- 获取对应的field-type节点 -->
            <xsl:variable name="target-fieldtype" select="key('fieldtype-by-id', @field-type-ref)"/>
            
            <!-- 添加field-type-ref:提取persistence-class-name的最后一部分(比如java.lang.Long → Long) -->
            <field-type-ref>
                <xsl:choose>
                    <xsl:when test="contains($target-fieldtype/persistence-class-name, '.')">
                        <xsl:value-of select="substring-after($target-fieldtype/persistence-class-name, 
                                                          substring-before($target-fieldtype/persistence-class-name, '.')
                                                          )"/>
                        <!-- 上面的写法对于多级包名也适用,比如a.b.c.Class → Class -->
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="$target-fieldtype/persistence-class-name"/>
                    </xsl:otherwise>
                </xsl:choose>
            </field-type-ref>
            
            <!-- 添加proxy-entity-ref:取field-type的proxy-ref属性值 -->
            <proxy-entity-ref>
                <xsl:value-of select="$target-fieldtype/@proxy-ref"/>
            </proxy-entity-ref>
        </field>
    </xsl:template>
</xsl:stylesheet>

代码解释

  • Key定义:category-by-id和fieldtype-by-id两个key分别用来快速通过identifier属性查找对应的<category>和<field-type>节点,避免了繁琐的路径遍历,提升效率。
  • 根模板:直接定位到所有需要处理的<field>元素,开始转换。
  • Field模板:
    1. 复制原<field>的identifier属性,保留原有结构。
    2. 用<xsl:copy-of>直接复制原有的<name>和<description>节点,不用重新构造。
    3. 通过key('category-by-id', @category-ref)找到对应的<category>,提取它的<name>值作为<category-ref-name>。
    4. 提取persistence-class-name的最后一部分:利用contains判断是否有包名分隔符,用substring-after和substring-before组合截取最后一段类名。
    5. 直接取对应<field-type>的proxy-ref属性值作为<proxy-entity-ref>的内容。

验证输出

将上述XSLT应用到你提供的示例XML,会生成完全符合你期望的输出结果:

<field identifier="ArticleID">
   <name>%field.name</name>
   <description>%field.Article.description</description>
   <category-ref-name>%category.parent</category-ref-name>
   <field-type-ref>Long</field-type-ref>
   <proxy-entity-ref>TypeA</proxy-entity-ref>
</field>
<field identifier="ArticleName">
   <name>%field.name.text</name>
   <description>%field.Articletext.description</description>
   <category-ref-name>%category.Texts</category-ref-name>
   <field-type-ref>String</field-type-ref>
   <proxy-entity-ref>TypeB</proxy-entity-ref>
</field>

内容的提问来源于stack exchange,提问作者Tester

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:25:29