【问题标题】:Java XML and XSLT transformation error: Namespace for prefix 'm' has not been declaredJava XML 和 XSLT 转换错误:前缀“m”的命名空间尚未声明
【发布时间】:2019-02-19 17:15:21
【问题描述】:

我正在尝试使用 javax.xml.transform.Transformer 和 XSLT 转换 XML 文档,但在调用转换方法时无法识别名称空间前缀。

这是定义了“m”命名空间前缀的 XML 文档:

<?xml version="1.0" encoding="UTF-8"?>
<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" Version="1.0">
  <edmx:DataServices xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:DataServiceVersion="1.0">
    <Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" Namespace="SITUATION">
    </Schema>
  </edmx:DataServices>
</edmx:Edmx>

这是目前仅复制整个 XML 文档的 XSL(稍后我想扩展它以合并到另一个 XML 文档中,类似于此处描述的内容:https://stackoverflow.com/a/5706319/208011):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- Copy everything including attributes as default action -->
    <xsl:template match="*">
        <xsl:element name="{name()}">
            <xsl:apply-templates select="@*" />
            <xsl:apply-templates />
        </xsl:element>
    </xsl:template>

    <xsl:template match="@*">
        <xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>
    </xsl:template>

</xsl:stylesheet>

这里是java代码:

Source xsltSource = new StreamSource(new File(getClass().getClassLoader().getResource("merge-metadata.xsl").getFile()));
transformer = transFact.newTransformer(xsltSource);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document input = dbf.newDocumentBuilder().parse(new InputSource(new StringReader(s1)));
StringWriter out = new StringWriter();
transformer.transform(new DOMSource(input), new StreamResult(out));

这是堆栈跟踪:

Caused by: java.lang.RuntimeException: Namespace for prefix 'm' has not been declared.
    at com.sun.org.apache.xml.internal.serializer.SerializerBase.getNamespaceURI(SerializerBase.java:915)
    at com.sun.org.apache.xml.internal.serializer.SerializerBase.addAttribute(SerializerBase.java:431)
    at com.sun.org.apache.xml.internal.serializer.ToUnknownStream.addAttribute(ToUnknownStream.java:316)

最终我想将此 XML 文档与另一个文档合并,但我无法解决命名空间问题而仅复制此文档。

如果我不在转换器工厂 newTransformer() 方法中使用 xsl 样式表,那么我不会收到命名空间错误,并且转换的输出与原始 XML 文档完全相同。

如果我将 DocumentBuilderFactory 设置为不支持命名空间,则不会出现异常,但转换的输出缺少命名空间。

感谢您的帮助。

【问题讨论】:

    标签: java xml xslt


    【解决方案1】:

    当您尝试使用未声明的命名空间前缀命名元素时,您手工制作的伪身份转换正在丢失命名空间声明并失败:

    <xsl:element name="{name()}">
    

    改用标准身份转换:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-26
      • 2014-03-21
      • 2017-04-09
      • 1970-01-01
      相关资源
      最近更新 更多