XSLT, concat values to comma separated string and

2019-06-01 01:00发布

问题:

How to convert XML1 to XML2?

In a further step (not part of this question) I should convert XML2 in JSON. The comma separated values must be then appear as arrays:

{111, 222};
{456};
{777,555};
{777,555};
{678};

Thanks so much in advance for your efforts, Thomas

XML1:

<transaction>
  <records type="1" >
      <record type="1" >
        <field number="1" >
            <subfield>
                <item>111</item>
                <item>222</item>
            </subfield>
        </field>
        <field number="2" >
            <subfield>
                <item>456</item>
            </subfield>
        </field>
      </record>
  </records>

  <records type="14" >
      <record type="14" >
        <field number="1" >
            <subfield>
                <item>777</item>
                <item>555</item>
            </subfield>
        </field>
        <field number="2" >
            <subfield>
                <item>678</item>
            </subfield>
        </field>
      </record>
  </records>
</transaction>

XML 2:

<transaction>
  <records type="1" >
      <record type="1" >
        <field number="1" >111,222</subfield>
        </field>
        <field number="2" >456</field>
      </record>
  </records>

  <records type="14" >
      <record type="14" >
        <field number="1" >777,555</field>
        <field number="2" >678</field>
      </record>
  </records>
</transaction>

回答1:

First, find a good book on XSLT and have a good read of it. See Where can I find a good tutorial on XSLT files? for suggestions.

Secondly, learn about the Identity Template....

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

With that in place, you are half-way there! You only need to then worry about transforming the subfield elements. That means you just need to add a template matching subfield which selects the item nodes.

<xsl:template match="subfield">
    <xsl:for-each select="item">
        <xsl:if test="position() > 1">,</xsl:if>
        <xsl:value-of select="." />
    </xsl:for-each>
</xsl:template>

Or, better still, if you can use XSLT 2.0, do this...

<xsl:template match="subfield">
    <xsl:value-of select="item" separator="," />
</xsl:template>

Try this XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:strip-space elements="*" />

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

    <xsl:template match="subfield">
        <xsl:value-of select="item" separator="," />
    </xsl:template>
</xsl:stylesheet>

This does assume one subfield per field though.



标签: xml xslt