2

在开发过程中使用 Visual Studio 执行转换,生成的 xml 包含来自目标中源 xml 的文本,该文本包含在与我的模板条件不匹配的标记中

我期待我在第一个模板中选择Group来找到任何名为Group的元素,它们是CrystalReport的直接子级,并在应用模板调用中传递它们。我知道我的第二个模板上的匹配过滤器只会接收具有Level=1属性的Group并将它们写出来。我希望其他一切都被忽略。

为什么“不是这个”出现在我的输出中?

资源

<?xml version="1.0" encoding="utf-8" ?>
<!--
 UPDATE: Note that adding the xmlns attribute causes all output
 to disappear unless you use Chris's second solution.
 -->
<CrystalReport xmlns="urn:crystal-reports:schemas:report-detail" >
  <Group Level="1">
    <GroupHeader>
      <Section>
        <Field FieldName="apple" />
      </Section>
    </GroupHeader>
    <Group Level="2">
      not this
    </Group>
  </Group>
</CrystalReport>

转换

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="/CrystalReport">
    <root>
        <xsl:apply-templates select="Group"/>
    </root>
  </xsl:template>

  <xsl:template match="Group[@Level='1']/GroupHeader">
    <tag1><xsl:value-of select="Section/Field/@FieldName"/></tag1>
  </xsl:template>
</xsl:stylesheet>

输出

<?xml version="1.0" encoding="utf-8"?>
<root>
  <tag1>apple</tag1>
      not this
    </root>
4

2 回答 2

2

您正面临 XML 解析器的内置模板发挥作用的问题。您将模板应用于所有Group元素,但仅使用您自己的模板捕获其中一个。另一个由输出所有节点值的默认模板处理。我建议你改变

 <xsl:template match="/CrystalReport">

进入

 <xsl:template match="/">

这将覆盖产生额外输出的根默认模板。您可以在http://www.w3.org/TR/xslt#built-in-rule找到有关内置模板规则的更多信息

然后覆盖基本的 text() 模板,使最终的 XSLT 看起来有点像这样

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
    <root>
        <xsl:apply-templates select="CrystalReport/Group"/>
    </root>
</xsl:template>
<xsl:template match="Group[@Level='1']/GroupHeader">
    <tag1>
        <xsl:value-of select="Section/Field/@FieldName"/>
    </tag1>
</xsl:template>
<xsl:template match="text()"/>

更新

或者更简单,您可以匹配所需的元素并使用类似的东西

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/CrystalReport">
    <root>
        <xsl:apply-templates select="Group[@Level='1']/GroupHeader"/>
    </root>
</xsl:template>
<xsl:template match="GroupHeader">
    <tag1>
        <xsl:value-of select="Section/Field/@FieldName"/>
    </tag1>
</xsl:template>

这将保留默认的 text() 模板,非常方便。

于 2012-04-11T10:25:51.877 回答
0

尝试

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:crystal="urn:crystal-reports:schemas:report-detail">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/crystal:CrystalReport">
    <root>
        <xsl:apply-templates select="crystal:Group[@Level='1']/crystal:GroupHeader"/>
    </root>
</xsl:template>
<xsl:template match="crystal:GroupHeader">
    <tag1>
        <xsl:value-of select="crystal:Section/crystal:Field/@FieldName"/>
    </tag1>
</xsl:template>

于 2012-04-11T11:27:58.713 回答