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

如何用XSLT提取XML中Subreport嵌套元素的名称与属性

问题描述

处理CrystalReport格式的XML文件,需要通过XSLT输出元素名称及其属性。当前转换已实现部分功能,但无法识别Subreport节点内的嵌套元素,需修改XSLT以包含这部分内容。

原始XML文件

<?xml version="1.0" encoding="UTF-8" ?>
<CrystalReport>
    <Details Level="2">
        <Section SectionNumber="0">
            <Field Name="IDNUMBER1">
                <Value>xxx</Value>
            </Field>
            <Field Name="TITLE1">
                <Value>aaa</Value>
            </Field>
            <Subreport Name="Subreport1">
                <ReportHeader> </ReportHeader>
                <Details Level="1">
                    <Section SectionNumber="0">
                        <Field Name="LASTSUFFNAME1">
                            <Value>bbb</Value>
                        </Field>
                        <Field Name="FIRSTMIDNAME1">
                            <Value>ccc</Value>
                        </Field>
                    </Section>
                </Details>
                <Details Level="1">
                    <Section SectionNumber="0">
                        <Field Name="LASTSUFFNAME1">
                            <Value>ddd</Value>
                        </Field>
                        <Field Name="FIRSTMIDNAME1">
                            <Value>eee</Value>
                        </Field>
                    </Section>
                </Details>
            </Subreport>
            <Field Name="MKEY1">
                <FormattedValue>111</FormattedValue>
                <Value>111</Value>
            </Field>
            <Field Name="DATE21">
                <Value>2023-07-13</Value>
            </Field>
        </Section>
    </Details>
</CrystalReport>

当前使用的XSLT代码

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>
  
    <xsl:template match="CrystalReport">
        <set>
            
            <xsl:apply-templates/>
            
        </set>
    </xsl:template>

    <xsl:template match="Details|Details/Section/Subreport/node()">
        <xsl:apply-templates select="Section/*"/>
        
    </xsl:template>
  
    <xsl:template match="Section/*">
        <xsl:for-each select=".">
        <attributeName>
            <xsl:value-of select="local-name()"/>
            <xsl:text> </xsl:text>
            <xsl:value-of select="@*"/>
          
        </attributeName>
        </xsl:for-each>
    </xsl:template> 
 
</xsl:stylesheet>

当前输出结果

<set>
   <attributeName>Field IDNUMBER1</attributeName>
   <attributeName>Field TITLE1</attributeName>
   <attributeName>Subreport </attributeName>
   <attributeName>Field MKEY1</attributeName>
   <attributeName>Field DATE21</attributeName>
</set>

期望输出结果

<set>
   <attributeName>Field IDNUMBER1</attributeName>
   <attributeName>Field TITLE1</attributeName>
   <attributeName>Field LASTSUFFNAME1</attributeName>
   <attributeName>Field FIRSTMIDNAME1</attributeName>
   <attributeName>Field LASTSUFFNAME1</attributeName>
   <attributeName>Field FIRSTMIDNAME1</attributeName>
   <attributeName>Field MKEY1</attributeName>
   <attributeName>Field DATE21</attributeName>
</set>
解决方案

问题出在原XSLT的模板匹配逻辑:未递归处理Subreport内部的Details节点,且错误输出了Subreport本身的信息。修改后的XSLT代码如下:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>
  
    <xsl:template match="CrystalReport">
        <set>
            <xsl:apply-templates/>
        </set>
    </xsl:template>

    <!-- 匹配所有层级的Details节点,处理其下的Section -->
    <xsl:template match="Details">
        <xsl:apply-templates select="Section"/>
    </xsl:template>

    <!-- 匹配Subreport节点,直接处理内部内容,跳过自身输出 -->
    <xsl:template match="Subreport">
        <xsl:apply-templates/>
    </xsl:template>

    <!-- 匹配Section节点,处理其下所有子元素 -->
    <xsl:template match="Section">
        <xsl:apply-templates select="*"/>
    </xsl:template>

    <!-- 专门匹配Field节点,生成目标输出 -->
    <xsl:template match="Field">
        <attributeName>
            <xsl:value-of select="local-name()"/>
            <xsl:text> </xsl:text>
            <xsl:value-of select="@Name"/>
        </attributeName>
    </xsl:template>

    <!-- 忽略不需要处理的节点(如ReportHeader、Value等) -->
    <xsl:template match="*[not(self::Field or self::Details or self::Section or self::Subreport)]"/>
</xsl:stylesheet>

代码说明

  • 单独匹配Subreport节点,直接递归处理内部所有内容,不输出Subreport自身信息
  • 匹配所有层级的Details节点,确保Subreport内的Details也能被处理
  • 针对Field节点单独生成输出,明确取@Name属性,避免意外匹配其他属性
  • 新增模板忽略无关节点,避免干扰最终输出

修改后即可正确捕获Subreport内部的所有Field元素,生成符合预期的输出结果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 13:07:46