1

I need to merge two XML files.

I tried writing an XSLT stylesheet based on the answer at Merge 2 XML files based on attribute values using XSLT?, but I was not successful.

_a1.xml

<?xml version="1.0" encoding="UTF-8"?>
<ExtData>
  <table bName="B SERs" id="BSER">
    <Col bName="Bus" id="BUS">
      <CoreCol coreEName="SER" coreHref="../_a2.xml" corebName="Bus" coreId="BUS"/>
    </Col>
    <Col bName="Ser" id="NAME">
      <CoreCol coreEName="SER" coreHref="../_a2.xml" corebName="Ser" coreId="NAME"/>
    </Col>
    <Col bName="ID" id="ID">
      <CoreCol coreEName="SER" coreHref="../_a2.xml" corebName="SerId" coreId="UCMDB_ID"/>
    </Col>
  </table>
</ExtData>

_a2.xml

<?xml version="1.0" encoding="UTF-8"?>
<ExtData>
  <table bName="B SERs" id="BSER">
    <Col EName="SER" bName="Bus" Id="BUS"/>
    <Col EName="SER" bName="Ser" Id="NAME"/>
    <Col EName="SER" bName="SerId" Id="DB_ID"/>
    <Col EName="SER" bName="SerDate" Id="date"/>
    <Col EName="SER" bName="Person" Id="Manager"/>
    <Col EName="SER" bName="desc" Id="desc"/>
  </table>
</ExtData>

And the output needs to be:

<?xml version="1.0" encoding="UTF-8"?>
<ExtData>
  <table bName="B SERs" id="BSER">
    <Col bName="Bus" id="BUS">
      <CoreCol coreEName="SER" coreHref="../_a2.xml" corebName="Bus" coreId="BUS"/>
    </Col>
    <Col bName="Ser" id="NAME">
      <CoreCol coreEName="SER" coreHref="../_a2.xml" corebName="Ser" coreId="NAME"/>
    </Col>
    <Col bName="ID" id="ID">
      <CoreCol coreEName="SER" coreHref="../_a2.xml" corebName="SerId" coreId="UCMDB_ID"/>
    </Col>
    <Col bName="" id="">
      <CoreCol coreEName="SER" coreHref="../_a2.xml" corebName="SerDate" coreId="date"/>
    </Col>
    <Col bName="" id="">
      <CoreCol coreEName="SER" coreHref="../_a2.xml" corebName="Person" coreId="Manager"/>
    </Col>
    <Col bName="" id="">
      <CoreCol coreEName="SER" coreHref="../_a2.xml" corebName="desc" coreId="desc"/>
    </Col>
  </table>
</ExtData>

Is it possible to do something like this with XSLT?

2
  • Can you use XSLT 2.0? Commented Feb 27, 2013 at 13:41
  • thank Eero!!!! I can use XSLT2 , but don't now how :) Commented Feb 27, 2013 at 15:18

1 Answer 1

1

I'm sure there's a better way, but here's the first XSLT 1.0 compatible option I came up with:

Stylesheet

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="table">
    <xsl:copy>
      <xsl:apply-templates select="@* | Col"/>
      <!--
      Apply <Col> elements in _a2.xml that have a @bName attribute that DOESN'T
      have a <CoreCol> element under the current <table> element with a
      corresponding @corebName attribute.
      -->
      <xsl:apply-templates
        select="document('_a2.xml')/ExtData/table[@id = current()/@id]
         /Col[not(current()/Col/CoreCol/@corebName = @bName)]" mode="merge"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="table/@bName">
    <xsl:copy/>
  </xsl:template>

  <!-- Match the elements applied in the template above. -->
  <xsl:template match="Col" mode="merge">
    <Col bName="" id="">
      <CoreCol>
        <xsl:apply-templates select="@EName"/>
        <xsl:attribute name="coreHref">../_a2.xml</xsl:attribute>
        <xsl:apply-templates select="@bName" mode="merge"/>
        <xsl:apply-templates select="@Id"/>
      </CoreCol>
    </Col>
  </xsl:template>

  <!-- Transform attribute names -->
  <xsl:template match="@EName">
    <xsl:attribute name="coreEName">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>

  <!--
  The @bName attributes in <Col> elements in _a2.xml need to be transformed
  into @coreBname elements in the output file. We'll use the "merge" mode so
  the @bName attributes in <Col> elements in _a1.xml aren't affected.
  -->
  <xsl:template match="@bName" mode="merge">
    <xsl:attribute name="corebName">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>

  <xsl:template match="@Id">
    <xsl:attribute name="coreId">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>

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

Comments

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.