简体   繁体   中英

Java XML and XSLT transformation error: Namespace for prefix 'm' has not been declared

I'm trying to transform an XML document with the javax.xml.transform.Transformer and XSLT, and am having trouble with a namespace prefix that is not recognized when I call the transform method.

Here is the XML document which has the "m" namespace prefix defined in it:

<?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>

Here is the XSL that currently just copies the whole XML document (later I'd like to extend it to merge in another XML document, similar to what is described here: 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>

Here is the java code:

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));

Here's the stack trace:

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)

Eventually I want to merge this XML document with another, but I can't get past the namespace issue to just copy this one.

If I don't use the xsl stylesheet in the transformer factory newTransformer() method then I don't get the namespace error and the output of the transformation is exactly the same as the original XML document.

If I set the DocumentBuilderFactory to not be namespace aware then I don't get the exception, but the output of the transformation is missing the namespaces.

Thanks for your help.

Your hand-crafted, pseudo-identity transform is losing the namespace declarations and failing when it tries to name an element with an undeclared namespace prefix:

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

Use the standard identity transformation instead:

<?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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM