Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT blank xmlns="" after transform

Tags:

xslt

transform

I'm using an XSLT to transform from one XML standard to another. The particular resulting XML standard contains a root element which is part of a namespace and a child node which is part of another namepsace.

The transform successfully reflects these namespaces but the child's child now contains a blank xmlns attribute. How can I prevent this xmlns=""?

XSLT Snippet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>

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

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

  <xsl:template match="REQUEST_GROUP">
    <ONCORE_ERECORD xmlns="http://test.com">
      <xsl:apply-templates select="REQUEST/PRIA_REQUEST/PACKAGE"/>
      <PAYMENT PaymentType="ACH" />
     <TRANSACTION_INFO _AgentKey="" _AgentPassword="" />
    </ONCORE_ERECORD>
 </xsl:template>

  <xsl:template match="PACKAGE">
    <DOCUMENT_RECORDATION xmlns="http://test2.org">
        <xsl:apply-templates select="PRIA_DOCUMENT"/>
    </DOCUMENT_RECORDATION>
  </xsl:template>

  <xsl:template match="PRIA_DOCUMENT">
    <PRIA_DOCUMENT _PRIAVersion="1.2">
      <xsl:attribute name="_Type">
        <xsl:value-of select="@RecordableDocumentType"/>
      </xsl:attribute>
      <xsl:attribute name="_Code"/>

  <xsl:apply-templates select="GRANTOR" />
  <xsl:apply-templates select="GRANTEE" />
  <xsl:choose>
    <xsl:when test="count(PROPERTY) = 0">
      <PROPERTY>
        <xsl:attribute name="_StreetAddress">
          <xsl:value-of select="@StreetAddress"/>
        </xsl:attribute>
        <xsl:attribute name="_StreetAddress2">
          <xsl:value-of select="@StreetAddress2"/>
        </xsl:attribute>
        <xsl:attribute name="_City">
          <xsl:value-of select="@City"/>
        </xsl:attribute>
        <xsl:attribute name="_State">
          <xsl:value-of select="@State"/>
        </xsl:attribute>
        <xsl:attribute name="_PostalCode">
          <xsl:value-of select="@PostalCode"/>
        </xsl:attribute>
        <xsl:attribute name="_County">
          <xsl:value-of select="@County"/>
        </xsl:attribute>
        <xsl:apply-templates select="LEGAL_DESCRIPTION"/>
      </PROPERTY>
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="PROPERTY" />
    </xsl:otherwise>
  </xsl:choose>
  <xsl:choose>
    <xsl:when test="count(PARTIES) = 0">
      <PARTIES>
        <_RETURN_TO_PARTY _UnparsedName="" _StreetAddress="" _StreetAddress2="" _City="" _State="" _PostalCode="" />
      </PARTIES>
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="PARTIES" />
    </xsl:otherwise>
  </xsl:choose>
  <xsl:apply-templates select="EXECUTION" />
  <xsl:apply-templates select="CONSIDERATION" />
  <xsl:apply-templates select="RECORDABLE_DOCUMENT/_ASSOCIATED_DOCUMENT" />
  <xsl:apply-templates select="EMBEDDED_FILE" />
</PRIA_DOCUMENT>

Source XML:

<REQUEST_GROUP PRIAVersionIdentifier="2.4">
  <REQUEST>
    <PRIA_REQUEST _Type="RecordDocuments">
      <PACKAGE>
        <PRIA_DOCUMENT PRIAVersionIdentifier="2.4" RecordableDocumentSequenceIdentifier="1" RecordableDocumentType="Mortgage">

Resulting XML:

<?xml version="1.0" encoding="utf-8"?>
<ONCORE_ERECORD xmlns="http://test.com">
  <DOCUMENT_RECORDATION xmlns="http://test2.org">
    <PRIA_DOCUMENT _PRIAVersion="1.2" _Type="Mortgage" _Code="" xmlns="">
like image 578
alan Avatar asked Aug 17 '10 16:08

alan


People also ask

What is exclude result prefixes in XSLT?

The optional exclude-result-prefixes attribute is a list, delimited by white-space, of the namespaces prefixes that should not be copied into the output (the result tree).

How does XSLT transform XML?

The standard way to transform XML data into other formats is by Extensible Stylesheet Language Transformations (XSLT). You can use the built-in XSLTRANSFORM function to convert XML documents into HTML, plain text, or different XML schemas. XSLT uses stylesheets to convert XML into other data formats.

How does XSLT transformation work?

XSLT Processor takes the XSLT stylesheet and applies the transformation rules on the target XML document and then it generates a formatted document in the form of XML, HTML, or text format. This formatted document is then utilized by XSLT formatter to generate the actual output which is to be displayed to the end-user.

What is match in XSLT?

The match attribute is used to associate a template with an XML element. The match attribute can also be used to define a template for the entire XML document. The value of the match attribute is an XPath expression (i.e. match="/" defines the whole document).


3 Answers

This is happening because PRIA_DOCUMENT is in the default namespace, while its parent DOCUMENT_RECORDATION is in a non-default namespace. You must put the PRIA_DOCUMENT in the same namespace as its parent, otherwise the serializer is required to generate xmlns="".

  .
  .
<xsl:template match="PRIA_DOCUMENT">
  <PRIA_DOCUMENT _PRIAVersion="1.2" xmlns="http://pria.org">
  .
  .
  .

See Michael Kay's "XSLT 2.0 and XPATH 2.0, 4th edition", page 475 where he discusses this exact situation.

like image 178
Jim Garrison Avatar answered Sep 26 '22 23:09

Jim Garrison


I found a solution that worked, though it may not have been the most efficient way to achieve the desired results.

I simply changed all literal element declarations to:

</xsl:element>

and declared the namespace. The resulting xslt is as follows:

<xsl:template match="REQUEST_GROUP">
<xsl:element name="ONCORE_ERECORD" namespace="http://test.com">
  <xsl:apply-templates select="REQUEST/PRIA_REQUEST/PACKAGE"/>
  <xsl:element name="PAYMENT" namespace="http://test.com">
    <xsl:attribute name="PaymentType">
      <xsl:value-of select="'ACH'"/>
    </xsl:attribute>
  </xsl:element>
  <xsl:element name="TRANSACTION_INFO" namespace="http://test.com">
    <xsl:attribute name="_AgentKey">
      <xsl:value-of select="''"/>
    </xsl:attribute>
    <xsl:attribute name="_AgentPassword">
      <xsl:value-of select="''"/>
    </xsl:attribute>
  </xsl:element>
</xsl:element>
  </xsl:template>

  <xsl:template match="PACKAGE">
<xsl:element name="DOCUMENT_RECORDATION" namespace="http://test2.org">
  <xsl:apply-templates select="PRIA_DOCUMENT"/>
</xsl:element>
  </xsl:template>

  <xsl:template match="PRIA_DOCUMENT">
<xsl:element name="PRIA_DOCUMENT" namespace="http://test2.org">
  <xsl:attribute name="_PRIAVersion">
    <xsl:value-of select="'1.2'"/>
  </xsl:attribute>
  <xsl:attribute name="_Type">
    <xsl:value-of select="@RecordableDocumentType"/>
  </xsl:attribute>
  <xsl:attribute name="_Code"/>

  <xsl:apply-templates select="GRANTOR" />
  <xsl:apply-templates select="GRANTEE" />
  <xsl:choose>
    <xsl:when test="count(PROPERTY) = 0">
        <xsl:element name="PROPERTY" namespace="http://test2.org">
          <xsl:attribute name="_StreetAddress">
            <xsl:value-of select="@StreetAddress"/>
          </xsl:attribute>
          <xsl:attribute name="_StreetAddress2">
            <xsl:value-of select="@StreetAddress2"/>
          </xsl:attribute>
          <xsl:attribute name="_City">
            <xsl:value-of select="@City"/>
          </xsl:attribute>
          <xsl:attribute name="_State">
            <xsl:value-of select="@State"/>
          </xsl:attribute>
          <xsl:attribute name="_PostalCode">
            <xsl:value-of select="@PostalCode"/>
          </xsl:attribute>
          <xsl:attribute name="_County">
            <xsl:value-of select="@County"/>
          </xsl:attribute>
          <xsl:apply-templates select="LEGAL_DESCRIPTION"/>
        </xsl:element>
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="PROPERTY" />
    </xsl:otherwise>
  </xsl:choose>
  <xsl:choose>
    <xsl:when test="count(PARTIES) = 0">
      <xsl:element name="PARTIES" namespace="http://test2.org">
        <xsl:element name="_RETURN_TO_PARTY" namespace="http://test2.org">
          <xsl:attribute name="_UnparseName">
            <xsl:value-of select="''"/>
          </xsl:attribute>
          <xsl:attribute name="_StreetAddress">
            <xsl:value-of select="''"/>
          </xsl:attribute>
          <xsl:attribute name="_StreetAddress2">
            <xsl:value-of select="''"/>
          </xsl:attribute>
          <xsl:attribute name="_City">
            <xsl:value-of select="''"/>
          </xsl:attribute>
          <xsl:attribute name="_State">
            <xsl:value-of select="''"/>
          </xsl:attribute>
          <xsl:attribute name="_PostalCode">
            <xsl:value-of select="''"/>
          </xsl:attribute>
        </xsl:element>
      </xsl:element>
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="PARTIES" />
    </xsl:otherwise>
  </xsl:choose>
  <xsl:apply-templates select="EXECUTION" />
  <xsl:apply-templates select="CONSIDERATION" />
  <xsl:apply-templates select="RECORDABLE_DOCUMENT/_ASSOCIATED_DOCUMENT" />
  <xsl:apply-templates select="EMBEDDED_FILE" />
    </xsl:element>
  </xsl:template> 
like image 42
alan Avatar answered Sep 26 '22 23:09

alan


I was having a similar issue even declaring the namespace on the child elements but was still ending up with

xmlns=""

I thought it was due to the xslt transformation but the string result of the transform was correct and it was when I then transformed the string to a org.w3c.dom.Document that the default namespaces were being added.

Making the DocumentBuilderFactory namespace aware fixed this

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document metadataDOM = db.parse(new ByteArrayInputStream(stringWriter.toString().getBytes()));
like image 28
Dan675 Avatar answered Sep 24 '22 23:09

Dan675