简体   繁体   中英

nested xml tag to xslt

Can you help me on this? I have an xml something like this

<x:person>
    <x:name>Angel</x:name>
    <x:education-info>
        <school>School ABC</school> 
        <address>address 123</address>
        <city>city 1</city> 
        <year>2001</year>
        <remarks>12334</remarks>
        <school>School ABC2</school>
        <address>address 456</address>
        <city>city 2</city>
        <year>2005</year>
        <remarks>test1233</remarks>
    </x:education-info>
    <x:age>22</x:age>
</x:person>

how can I get only school and address tag inside education-info tag ? and format it to xslt something like this

School ABC - address 123
School ABC2 - address 456

XSLT 1.0

If I first make your XML valid XML, it will look something like the following, which has the effect that some elements are in namespace urn:yourns and some are in no namespace:

<x:person xmlns:x="urn:yourns">
    <x:name>Angel</x:name>
    <x:education-info>
        <school>School ABC</school> 
        <address>address 123</address>
        <city>city 1</city> 
        <year>2001</year>
        <remarks>12334</remarks>
        <school>School ABC2</school>
        <address>address 456</address>
        <city>city 2</city>
        <year>2005</year>
        <remarks>test1233</remarks>
    </x:education-info>
    <x:age>22</x:age>
</x:person>

Now, if you want data from this input, you will need to make sure to match the proper namespace in your XSLT. It does not have to match the prefix, as long as it matches the namespace.

The following code shows how to do this the "XSLT way" by using templates. This may look like more code than the first answer, but it is more resilient to change:

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

    <!-- select 'text', as your output suggests you only want text -->
    <xsl:output method="text" />

    <!-- ignore what we aren't interested in (this one is not req. with 
    your data, but help if your input is larger/different) -->
    <xsl:template match="node()">
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="text()" />

    <!-- match parent x:education-info to only select what we are interested in 
    (this one can be left out as well, but more cleanly shows what you want to do)-->
    <xsl:template match="your:education-info">
        <xsl:apply-templates select="school | address" />
    </xsl:template>

    <!-- match school in no-namespace -->
    <xsl:template match="school">
        <xsl:value-of select="." />
        <xsl:text> - </xsl:text>
    </xsl:template>

    <!-- match address in no-namespace -->
    <xsl:template match="address">
        <xsl:value-of select="." />
        <xsl:text>&#xa;</xsl:text>
    </xsl:template>

</xsl:stylesheet>

The output, when run against your input is the following. Check it online by clicking here .

School ABC - address 123
School ABC2 - address 456

XSLT 3.0

For the fun of it, or mainly because your example is so clearly cut out for a call on for-each-pair , here's a one-liner (if you ignore the bloat) in XSLT 3.0:

<xsl:stylesheet version="3.0" xmlns:your="urn:yourns"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text" />
    <xsl:mode on-no-match="shallow-skip" />

    <xsl:template match="your:education-info">
        <xsl:value-of separator="&#xA;" select="
           for-each-pair(school, address, 
           function($a, $b) {$a ||  ' - ' ||  $b })" />
    </xsl:template>

</xsl:stylesheet>

Something along the lines of (I didn't have your namespace x, so omitting it here):

<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <xsl:for-each select="person/education-info/school">
      <xsl:value-of select="."/>
      <xsl:text> - </xsl:text>
      <xsl:value-of select="following-sibling::address[1]"/>
      <xsl:text>&#xa;</xsl:text>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

This gives me:

School ABC - address 123
School ABC2 - address 456

EDIT: Specify [1] in following-sibling to request only first.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM