XSLT: flatten tree

Ruebe

I'd like to convert Kodi-compatible xml to Xtreamer-compatible xml. The input looks like this:

<?xml version="1.0" encoding="utf-8"?>
<movie xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <id>something</id>
  <title>something</title>
  <originaltitle>something</originaltitle>
...and so on... several unknown nodes
  <actor>
    <name>Name1</name>
    <role>Role1</role>
    <order>0</order>
  </actor>
  <actor>
    <name>Name2</name>
    <role>Role2</role>
    <order>1</order>
  </actor>
  <actor>
    <name>Name3</name>
    <role>Role3</role>
    <order>2</order>
  </actor>
...several other unknown nodes...
</movie>

What I'd like to have is:

<?xml version="1.0" encoding="utf-8"?>
<movie xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <id>something</id>
  <title>something</title>
  <originaltitle>something</originaltitle>
...and so on... several unknown nodes
  <actor>
    <name>Name1</name>
    <name>Name2</name>
    <name>Name3</name>
  </actor>
...several other unknown nodes...
</movie>

...so just drop every child item of actor besides name and put all the names into one common actor tag. The rest of the document should stay unchanged.

What I tried is:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/REC-html40">

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

<xsl:template match="/movie">
 <actor>
 <xsl:for-each select="actor">
 <xsl:apply-templates select="name"/>
 </xsl:for-each>
 </actor>
 <xsl:apply-templates/>
 </xsl:template>


</xsl:stylesheet>

What I get is:

<?xml version="1.0"?>
<actor xmlns="http://www.w3.org/TR/REC-html40"><name xmlns="">Name1</name><name xmlns="">Name2</name><name xmlns="">Name3</name></actor>
<id>something</id>
<title>something</title>
<originaltitle>something</originaltitle>
...and so on... several unknown nodes
<actor>
<name>Name1</name>
<role>Role1</role>
<order>0</order>
</actor>
<actor>
<name>Name2</name>
<role>Role2</role>
<order>1</order>
</actor>
<actor>
<name>Name3</name>
<role>Role3</role>
<order>2</order>
</actor>
...several other unknown nodes...

Some things don't work work like wanted:

  1. All the actor-nodes and their children are still in the output.
  2. The actor-name-name-name-actor-Block:
    • replaces the movie-tag
    • is in the beginning, not at the position, where the actor-nodes used to be before
    • has no line breaks

Any help would be appreciated.

cvesters

I have come up with this:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

<xsl:template match="actor[1]">
<xsl:copy>
<xsl:copy-of select="../actor/name" />
</xsl:copy>
</xsl:template>

<xsl:template match="actor" />

</xsl:stylesheet>

Instead of using the movie element, I transform the actors. This prevents the movie tag from disappearing, and it will keep the actors in place.

There are two rules for actor, Only the first element will actually select all the names. The other will just remain blank.

The line breaks are still not correct though. But I think it's a bit weird you are so focused on line breaks, as they do not matter in XML. But perhaps you want it so it is more readable.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related