【问题标题】:Error designing template XSLT to generate XML设计模板 XSLT 以生成 XML 时出错
【发布时间】:2017-07-11 21:31:51
【问题描述】:

我需要生成这个 XML:

<bdo_fosfec:RegistrosPagosElement xsi:type="bdo_fosfec:RegistrosPagos" 
 xmlns:bdo_fosfec="http://asocajas.app.com/example" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <registro54 xsi:type="bdo_fosfec:Registro54">
   <registro82 xsi:type="bdo_fosfec:Registro82">
     <C512>39756656</C512>
     <C614>YAXMINNI</C614>
   </registro82>
 </registro54>
 <registro54 xsi:type="bdo_fosfec:Registro54">
   <registro82 xsi:type="bdo_fosfec:Registro82">
     <C512>79374740</C512>
     <C614>VICTOR</C614>
   </registro82>
 </registro54>
</bdo_fosfec:RegistrosPagosElement>

我构建了这个 XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
 <xsl:template match="/">
   <bdo_fosfec:RegistrosPagosElement xsi:type="bdo_fosfec:RegistrosPagos" xmlns:bdo_fosfec="http://asocajas.app.com/example" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <xsl:apply-templates select="registro54"/>
   </bdo_fosfec:RegistrosPagosElement>
 </xsl:template>
 <!--TEMPLATE REGISTRO 54-->
 <xsl:template match="registro54">
   <registro54 xsi:type="bdo_fosfec:Registro54">
        <registro82 xsi:type="bdo_fosfec:Registro82">
          <C512><xsl:value-of select="C512"/></C512>
          <C614><xsl:value-of select="C614"/></C614>
        </registro82>
   </registro54>
 </xsl:template>
</xsl:stylesheet>

但是,当我在 C# 上加载 XSLT 时,出现错误。

var xslt = new XslCompiledTransform();
xslt.Load(myxslt);

XSLT 编译错误。 'xsi' 是一个未声明的前缀。第 11 行,第 19 位。

好像第二个模板的“xsi”无法达到第一个模板的定义。如何修复我的 XSLT?

我对 XSLT 做了一些修改,但没有生成我想要的结果,正确的 xslt 设计是什么?

【问题讨论】:

  • 尝试将xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 添加到xsl:stylesheet 元素。
  • 您需要声明要在 XSL 代码中使用的任何命名空间。由于您的 XSL 从未声明带有前缀 xsi 的命名空间,因此 XSL 处理器无法处理它,因此会引发错误。
  • @EiríkrÚtlendi - 我认为如果你将我们的两个 cmets 结合起来,那将是一个不错的答案。如果您创建答案,我会很高兴地支持它。 :)
  • @DanielHaley rigth,这解决了我的错误,但结果 xml 不符合预期.. jumm... 无论如何,我会尝试一些事情。
  • @Makitodev - 如果您最终需要更多帮助,请创建一个新问题。

标签: c# xml xslt


【解决方案1】:

XSL 中的命名空间(和前缀)可能很棘手。

您需要声明要在 XSL 代码中使用的任何命名空间。由于您的 XSL 以有限的方式声明了带有前缀 xsi 的命名空间,因此当该前缀出现在声明范围之外时,XSL 处理器无法处理该前缀,因此会引发错误。

尝试将 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 添加到 XSL 中最顶部的 xsl:stylesheet 元素。分解:

  • xmlns 代表“XML namespace”。
  • xsi 是您要使用的前缀。这可以是任何东西——它不必匹配输入 XML 中的前缀。
  • http://www.w3.org/2001/XMLSchema-instance 部分是标识命名空间的 URI 字符串。这部分必须与输入 XML 中的命名空间 URI 匹配,否则您的模板将无法匹配。

我注意到您确实在不同的元素上添加了命名空间声明:bdo_fosfec:RegistrosPagosElement。这是有效的 XSL,但是这个命名空间只适用于这个元素的子元素。 xsi 前缀(指向此命名空间)也用于您的 XSL 代码中的不同模板中,并且由于 bdo_fosfec:RegistrosPagosElement 中命名空间声明的范围未扩展到此其他模板,因此您的 XSL 处理器正确失败编译你的代码。

修复后的样子:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">
        <bdo_fosfec:RegistrosPagosElement xsi:type="bdo_fosfec:RegistrosPagos"
            xmlns:bdo_fosfec="http://asocajas.app.com/example">
            <xsl:apply-templates select="registro54"/>
        </bdo_fosfec:RegistrosPagosElement>
    </xsl:template>

    <!--TEMPLATE REGISTRO 54-->
    <xsl:template match="registro54">
        <registro54 xsi:type="bdo_fosfec:Registro54">
            <registro82 xsi:type="bdo_fosfec:Registro82">
                <C512><xsl:value-of select="C512"/></C512>
                <C614><xsl:value-of select="C614"/></C614>
            </registro82>
        </registro54>
    </xsl:template>
</xsl:stylesheet>

【讨论】:

  • 问题链接是这个stackoverflow.com/questions/45045625/…thnks的下一个
  • @Makitodev:刚刚发布到那里。 :) 干杯!
  • @Makitodev - 请务必通过单击旁边的复选标记来接受此答案。 (See here 了解更多详情。)
猜你喜欢
  • 2017-12-16
  • 1970-01-01
  • 1970-01-01
  • 2012-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-10
相关资源
最近更新 更多