Subject: Namespace copy problem
Posted By: francislang Post Date: 2/20/2006 8:25:51 AM
I have an XML document similar to this:

<?xml version="1.0" ?>
<Document xmlns="http://mydomain.com/DocumentSchema.xsd">
    <Submission>
        <AddressDetails>
            <Flat />
            <HouseName />
            <HouseNumber>1</HouseNumber>
            <Street>Test Street</Street>
            <District>Test District</District>
            <Town>Test Town</Town>
            <County>test County</County>
            <Postcode>TEST123</Postcode>
        </AddressDetails>
        <BankDetails>
            <SortCode/>
            <AccountNumber/>
        </BankDetails>
    </Submission>
</Document>

I have got a problem with some XSL. Basically I want my output to select all the nodes including <AddressDetails> to give:

<?xml version="1.0" ?>
<AddressDetails>
    <Flat />
    <HouseName />
    <HouseNumber>1</HouseNumber>
    <Street>Test Street</Street>
    <District>Test District</District>
    <Town>Test Town</Town>
    <County>test County</County>
    <Postcode>TEST123</Postcode>
</AddressDetails>

I think it is the namespace that is causing the issue.

My XSL is as follows:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:test="http://mydomain.com/DocumentSchema.xsd" exclude-result-prefixes="test">
  <xsl:output method="xml" indent="no"/>
  <xsl:template match="test:Submission">
        <xsl:element name="AddressDetails">
            <xsl:copy-of select="*" />
            <xsl:apply-templates mode="copy-no-ns" select="node()" />
        </xsl:element>
    </xsl:template>
    <xsl:template mode="copy-no-ns" match="*">
        <xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
            <xsl:copy-of select="@*" />
            <xsl:apply-templates mode="copy-no-ns" />
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

The result includes BankDetails as well.

If I change the xsl:template match to "test:AddressDetails" it errors with "The data at the root level is invalid."

Any help would be most appreciated.



Reply By: mhkay Reply Date: 2/20/2006 10:16:22 AM
Just add a template rule that throws away the BankDetails:

<xsl:template mode="copy-no-ns" match="test:BankDetails"/>

Also, this is quite wrong:

  <xsl:template match="test:Submission">
        <xsl:element name="AddressDetails">
            <xsl:copy-of select="*" />
            <xsl:apply-templates mode="copy-no-ns" select="node()" />
        </xsl:element>
    </xsl:template>

The xsl:copy-of select="*" copies all children of the Submission, which you don't want. I would get rid of this rule and replace it with

<xsl:template match="/">
  <xsl:apply-templates select="//test:AddressDetails"/>
</xsl:template>

The error you report looks like a red herring.


Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply By: francislang Reply Date: 2/20/2006 10:46:45 AM
Thanks Mike. That's pretty much it except I'm only getting the data from the XML elements. The nodes appear to be missing.

The following XSL:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:test="http://mydomain.com/DocumentSchema.xsd" exclude-result-prefixes="test">
    <xsl:output method="xml" indent="no" />
    <xsl:template match="/">
        <xsl:element name="AddressDetails">
            <xsl:apply-templates select="//test:AddressDetails/node()" />
        </xsl:element>
    </xsl:template>
    <xsl:template mode="copy-no-ns" match="*">
        <xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
            <xsl:copy-of select="@*" />
            <xsl:apply-templates mode="copy-no-ns" />
        </xsl:element>
    </xsl:template>
    <xsl:template mode="copy-no-ns" match="test:BankDetails" />
</xsl:stylesheet>

Gives:

<?xml version="1.0" ?>
<AddressDetails>1Test StreetTest DistrictTest Towntest CountyTEST123</AddressDetails>

Is it possible to get the elements as well?


Reply By: mhkay Reply Date: 2/20/2006 12:07:42 PM
Your terminology is a bit off: an element is a kind of node.

You need to specify mode="copy-no-ns" on the apply-templates call (or remove it from the template rules).

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference

Go to topic 30220

Return to index page 365
Return to index page 364
Return to index page 363
Return to index page 362
Return to index page 361
Return to index page 360
Return to index page 359
Return to index page 358
Return to index page 357
Return to index page 356