XSL文件子元素无法填充问题:父标签加静态值后孙元素不匹配模板
为父标签添加静态属性后,孙标签无法通过template-match填充的解决方法
当给<Vocabulary>标签加上静态属性type="abc:def:ijk:Location"后,它下面的<VocabularyElement>标签没法通过template-match规则完成填充。试过template-match和for-each都没解决,相关输入、现有XSLT及期望输出如下:
输入XML
<VocabularyList> <Vocabulary> <VocabularyElementList> <VocabularyElement> <Number>1234674</Number> </VocabularyElement> <VocabularyElement> <Number>1234675</Number> </VocabularyElement> </VocabularyElementList> </Vocabulary> </VocabularyList>
现有XSLT代码
<xsl:template match="VocabularyList/Vocabulary"> <Vocabulary type="abc:def:ijk:Location"/> </xsl:template> <xsl:template match="VocabularyList/Vocabulary/VocabularyElementList/VocabularyElement/Number"> <VocabularyElement id="abc:def:ijk:{substring(.,1,15)}"/> </xsl:template> <xsl:template match="Header/Data/VocabularyList/Vocabulary"> <Vocabulary type="abc:def:ijk:Location"> <xsl:element name="VocabularyElementList"> <xsl:element name="VocabularyElement"> <xsl:for-each select ="VocabularyElement/Number"> <VocabularyElement id="abc:def:ijk:{substring(.,1,15)}"/> </xsl:for-each> </xsl:element> </xsl:element> </Vocabulary> </xsl:template>
期望输出
<VocabularyList> <Vocabulary type="abc:def:ijk:Location"> <VocabularyElementList> <VocabularyElement id="abc:def:ijk:1234674"> <attribute id="abc:def:ijk#name">Company One</attribute> </VocabularyElement> <VocabularyElement id="abc:def:ijk:1234675"> <attribute id="abc:def:ijk#name">Company Two</attribute> </VocabularyElement> </VocabularyElementList> </Vocabulary> </VocabularyList>
问题原因分析
- 第一个匹配
VocabularyList/Vocabulary的模板直接输出了自闭合的<Vocabulary>标签,没加<xsl:apply-templates/>处理子节点,导致<VocabularyElementList>及其下面的内容完全被跳过,后续匹配Number的模板根本没机会执行。 - 第三个模板的匹配路径
Header/Data/VocabularyList/Vocabulary和输入XML的结构不对应,输入里没有Header/Data这一层,所以这个模板根本不会触发。 - 匹配
Number的模板直接输出<VocabularyElement>,既没保留原有的<VocabularyElementList>结构,也没生成期望的<attribute>子节点。
修正后的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 保留VocabularyList结构,处理其子节点 --> <xsl:template match="VocabularyList"> <xsl:copy> <xsl:apply-templates/> </xsl:copy> </xsl:template> <!-- 处理Vocabulary节点,添加静态属性并继续处理子节点 --> <xsl:template match="VocabularyList/Vocabulary"> <Vocabulary type="abc:def:ijk:Location"> <xsl:apply-templates/> </Vocabulary> </xsl:template> <!-- 保留VocabularyElementList结构 --> <xsl:template match="VocabularyElementList"> <xsl:copy> <xsl:apply-templates/> </xsl:copy> </xsl:template> <!-- 处理VocabularyElement节点,生成带id的标签和attribute子节点 --> <xsl:template match="VocabularyElement"> <VocabularyElement id="abc:def:ijk:{Number}"> <attribute id="abc:def:ijk#name"> <xsl:choose> <xsl:when test="Number='1234674'">Company One</xsl:when> <xsl:when test="Number='1234675'">Company Two</xsl:when> </xsl:choose> </attribute> </VocabularyElement> </xsl:template> <!-- 忽略原Number节点,避免输出原数字内容 --> <xsl:template match="Number"/> </xsl:stylesheet>
修正说明
- 在
Vocabulary模板里加了<xsl:apply-templates/>,确保它的子节点能被后续模板处理,不会被跳过。 - 新增了匹配
VocabularyElementList的模板,保留原有的层级结构。 - 把匹配逻辑调整为直接处理
VocabularyElement节点,从它的Number子节点取值生成id属性,同时通过xsl:choose生成对应公司名称的<attribute>子节点(实际场景可根据需求调整名称生成逻辑)。 - 添加了忽略
Number节点的模板,避免原数字内容被直接输出。
应用这段修正后的XSLT,就能得到和期望一致的输出结果。
内容的提问来源于stack exchange,提问作者Viji
相关产品推荐
相关产品推荐

