2

I have two XML objects that I believe describe the same entity, one uses namespace prefixes, and one uses inline namespace declarations. I want to diff them, but the different ways of representing the namespace make that all but impossible.

How can I take the first xml snippet below and change it to match the second snippet?

<!--I want to take data that looks like this-->
<Foo xmlns:e="http://schemas.cch.com/FooBar/MDS/2007/12/04/Foo">
  <e:Description></e:Description>
  <e:Name i:nil="true"></e:Name>
  <e:DisplaySeqNo>0</e:DisplaySeqNo>
</Foo>

<!--I want to make that data that looks like this-->
<Foo>
  <Description xmlns="http://schemas.cch.com/FooBar/MDS/2007/12/04/Foo"></Description>
  <Name i:nil="true" xmlns="http://schemas.cch.com/FooBar/MDS/2007/12/04/Foo"></Name>
  <DisplaySeqNo xmlns="http://schemas.cch.com/FooBar/MDS/2007/12/04/Foo">0</DisplaySeqNo>
</Foo>

The requirement to diff them is part of a manual debugging process process, so I'd be happy with a web tool, script, or whatever. I don't plan on doing this regularly but am ripping my hair out trying to figure out how xml sample A is different than xml sample B.

4
  • Are you OKI with using XSLT-1.0? Commented Feb 6, 2020 at 21:56
  • Preferred languages or technologies for a non-XSLT solution? Commented Feb 6, 2020 at 21:58
  • @Amy I've never used XSLT, so I don't know if I'm ok with it or not, but if a snippet can get me from A to B I'd be more than happy to use it. Commented Feb 6, 2020 at 21:59
  • My current thinking is you could start with and adapt this code, except instead of removing, you replace. I think localname() would need to become name(). I think. My knowledge of XSLT is rather limited. Commented Feb 6, 2020 at 22:02

1 Answer 1

2

You can use the following XSLT-1.0 stylesheet. It's a combination of the Identity template (which copies all nodes) with two templates handling the replacement situation:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:e="http://schemas.cch.com/FooBar/MDS/2007/12/04/Foo">
    <xsl:output method="xml" indent="yes"/>

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

    <xsl:template match="Foo">
      <xsl:element name="{local-name()}" namespace="">
        <xsl:apply-templates select="node()|@*" />
      </xsl:element>
    </xsl:template>

    <xsl:template match="e:*">
      <xsl:element name="{local-name()}" namespace="http://schemas.cch.com/FooBar/MDS/2007/12/04/Foo">
        <xsl:apply-templates select="node()|@*" />
      </xsl:element>
    </xsl:template>    

</xsl:stylesheet>

Its output is:

<Foo>
  <Description xmlns="http://schemas.cch.com/FooBar/MDS/2007/12/04/Foo"/>
  <Name xmlns="http://schemas.cch.com/FooBar/MDS/2007/12/04/Foo" i:nil="true"/>
  <DisplaySeqNo xmlns="http://schemas.cch.com/FooBar/MDS/2007/12/04/Foo">0</DisplaySeqNo>
</Foo>

It also produces an error for the XML file, because the i namespace is not defined in it. It also copies the comment from the input XML, but I guess that was just a comment for illustration and can therefore be ignored.

If you're using some kind of Linux, you can easily pass this template to xsltproc.

Sign up to request clarification or add additional context in comments.

1 Comment

Just an FYI, in windows this can be done by having an xml file, adding a xslt file to the xml file's stylesheet property, then choosing to start xslt (with or without debugging) from visual studio. (Also, thank you!)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.