0

I am having a problem where nothing is being replaced.

I looked at other SO issues to rename nodes and to replace values, and have copied the examples from the answers, but nothing is working for me. I suspect that I have something subtly wrong, but I have reviewed my C#, XML, and XSL code, and can't seem to find it.

Here is my C# code:

private static string GetOutput(string xmlFileName, string xslFileName)
{
    var xmlDocument = new XmlDocument();
    xmlDocument.Load(xmlFileName);

    var xslTransform = new XslCompiledTransform();
    xslTransform.Load(xslFileName);

    var stream = new MemoryStream();
    xslTransform.Transform(xmlDocument, null, stream);

    stream.Position = 1;
    var reader = new StreamReader(stream);
    string output = reader.ReadToEnd();

    return output;
}

Here is my the contents of my XML file:

<?xml version="1.0" encoding="utf-8" ?>
<TransformThis xmlns="http://schemas.datacontract.org/2004/07/TransformTest" 
             xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <f_name>John</f_name>
    <l_name>D&apos;Oh!</l_name>
    <Version>1.0</Version>
</TransformThis>

And here is the contents of my XSL file:

<?xml version="1.0" encoding="utf-8"?>
<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:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Version/text()[.='1.0']">1.1</xsl:template>

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

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

</xsl:stylesheet>

When I run my program, the output is the same as the original XML. Neither the f_name and l_name nodes have been renamed, nor has the Version node value been replaced.

Any help would be greatly appreciated.

UPDATE Per michael.hor257k's answer below, I have modified my XLS file as follows:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:tx="http://schemas.datacontract.org/2004/07/TransformTest"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
                exclude-result-prefixes="msxsl">

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

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

    <xsl:template match="tx:Version/text()[.='1.0']">1.1</xsl:template>

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

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

</xsl:stylesheet>

I added the ...TransformTest namespace to the XLS file, and prefixed the match nodes with tx:.

Now the transformation is working, but it is also added the tx: namespace to the renamed nodes:

<?xml version="1.0" encoding="utf-8"?>
<Transformer xmlns="http://schemas.datacontract.org/2004/07/TransformTest" 
             xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <FirstName xmlns="" xmlns:tx="http://schemas.datacontract.org/2004/07/TransformTest">John</FirstName>
    <LastName xmlns="" xmlns:tx="http://schemas.datacontract.org/2004/07/TransformTest">Doh</LastName>
    <Version>1.1</Version>
</Transformer>

Also, when the XML is deserialized into an object, the LastName and FirstName properties are null, which I suspect has something to do with the additional namespace attributes on those nodes.

I would like the output to look just like the original XML, but with only the names and values changed.

UPDATE #2 michael.hor257k ADDED: an example XLS file in his answer. This resolved all of my issues.

1 Answer 1

1

Neither the f_name and l_name nodes have been renamed, nor has the Version node value been replaced.

These elements are children of the <TransformThis> element which has its own namespace. You must declare this namespace in your stylesheet, assign it a prefix and use the prefix when addressing the element or its descendants.


ADDED:
Try it this way? Note that this is a bit tricky, because you are essentially adding new children to an existing (copied) parent. These new elements do not automatically inherit the namespace of their adoptive parent, and they need to have it assigned to them explicitly.

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://schemas.datacontract.org/2004/07/TransformTest"
exclude-result-prefixes="ns">

<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

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

<xsl:template match="ns:Version/text()[.='1.0']">1.1</xsl:template>

<xsl:template match="ns:f_name">
    <xsl:element name="FirstName" namespace="http://schemas.datacontract.org/2004/07/TransformTest">
        <xsl:apply-templates select="node()|@*"/>
    </xsl:element>
</xsl:template>

<xsl:template match="ns:l_name">
    <xsl:element name="LastName" namespace="http://schemas.datacontract.org/2004/07/TransformTest">
        <xsl:apply-templates select="node()|@*"/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, @Michael.hor257k. I knew I was doing something wrong. Can you provide an example?
@Weltonv3.53 Do you want to preserve the original namespace in the result?
Yes, if possible. I did some experimenting and added the namespace of the XML file to the XSL, and prefixed the node names, and it did replace the node names and values, but it also added the namespace to the renamed nodes. Then when I deserialized the XML into an object, the values for those nodes was missing. Ideally, I would like the output to look just like the original XML, but with only the names and values changed.
@Weltonv3.53 I have added a stylesheet to my answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.