XSLT删除节点但保留内容

3

我试图删除节点名称但保留内容,或将节点内容复制到其父节点。我从SSRS导出XML并将XSLT文件附加到报告RDL。我觉得我的xslt已经非常接近了。我试图删除在文件中频繁重复的“Cell”节点。

我想要这个:

<ReportSectionAPercentLabel>
    <Cell>
        <losPct>0.262158054711246</losPct>
    </Cell>
</ReportSectionAPercentLabel>

要呈现如下效果:
<ReportSectionAPercentLabel>
    <losPct>0.262158054711246</losPct>
</ReportSectionAPercentLabel>

这是XML中的一部分内容:

这是一个XML片段:

<?xml version="1.0" encoding="UTF8"?>
<Report xmlns="My_Report" Name="My report">
<ReportSectionATablix>
    <ReportSectionARowGroup_Collection>
        <ReportSectionARowGroup>
            <losProvider>Your Enterprise</losProvider>
            <ReportSectionAColumnGroup_Collection>
                <ReportSectionAColumnGroup>
                    <ReportSectionAGroupLabel>07</ReportSectionAGroupLabel>
                    <ReportSectionACountLabel>
                        <Cell>
                            <ReportSectionACount>345</ReportSectionACount>
                        </Cell>
                    </ReportSectionACountLabel>
                    <ReportSectionAPercentLabel>
                        <Cell>
                            <losPct>0.262158054711246</losPct>
                        </Cell>
                    </ReportSectionAPercentLabel>
                </ReportSectionAColumnGroup>
                <ReportSectionAColumnGroup>
                    <ReportSectionAGroupLabel>814</ReportSectionAGroupLabel>
                    <ReportSectionACountLabel>
                        <Cell>
                            <ReportSectionACount>153</ReportSectionACount>
                        </Cell>
                </ReportSectionACountLabel>
                ...

这是XSLT代码。我选错了Cell的Xpath路径吗?

<xsl:template match="node()|@*" >
   <xsl:copy>
      <xsl:apply-templates select="node()|@*" />
   </xsl:copy>
</xsl:template>

<xsl:template match="Cell" >
   <xsl:apply-templates select="*" />
</xsl:template>

1个回答

4
你的方法是正确的,但问题出在命名空间上。在你的XML中,你有一个默认命名空间声明(xmlns)。
<Report xmlns="My_Report" Name="My report">

这意味着该元素及其所有后代都属于该命名空间(除非被另一个命名空间声明覆盖)。但是在您的XSLT中,您已将Cell指定为模板匹配项,这将寻找没有命名空间的Cell元素,与具有命名空间的XML中的Cell不匹配。

解决方案是在XSLT中使用前缀声明该命名空间,并在匹配Cell元素时使用该前缀:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:rep="My_Report">
   <xsl:template match="node()|@*" >
      <xsl:copy>
         <xsl:apply-templates select="node()|@*" />
      </xsl:copy>
   </xsl:template>

   <xsl:template match="rep:Cell" >
      <xsl:apply-templates select="*" />
   </xsl:template>
</xsl:stylesheet>

另外,如果您使用的是XSLT 2.0,您可以使用 xpath-default-namespace,在这种情况下,任何没有命名空间前缀的Xpath表达式都被假定为在该默认命名空间中。

这也可以起作用...

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xpath-default-namespace="My_Report">
   <xsl:template match="node()|@*" >
      <xsl:copy>
         <xsl:apply-templates select="node()|@*" />
      </xsl:copy>
   </xsl:template>

   <xsl:template match="Cell" >
      <xsl:apply-templates select="*" />
   </xsl:template>
</xsl:stylesheet>

如果出于任何原因,您想要避免在XSLT中编写命名空间声明,您可以将模板匹配更改为以下内容:

<xsl:template match="*[local-name()='Cell']" >

非常感谢您的解释。A)我不理解命名空间,B)现在我知道,我需要为每个指定命名空间,而不是使用标准模板来生成SSRS输出。谢谢! - BClaydon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接