XSLT:展平树

时间:2015-07-18 07:30:15

标签: xml xslt

我想将与Kodi兼容的xml转换为与Xtreamer兼容的xml。 输入如下所示:

<?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>

我想拥有的是:

<?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>

...所以只需删除除名称之外的每个actor子项,并将所有名称放入一个公共actor标记中。文件的其余部分应保持不变。

我尝试的是:

<?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>

我得到的是:

<?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...

有些事情不能像想要的那样工作:

  1. 所有演员节点及其子节点仍在输出中。
  2. 的 演员名称名称名称演员块:
    • 替换movie-tag
    • 位于开头,而不是位于演员节点之前的位置
    • 没有换行符
  3. 任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:1)

我想出了这个:

<?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>

我没有使用电影元素,而是改变了演员。这可以防止电影标签消失,并且可以保持演员的位置。

actor有两个规则,只有第一个元素才能实际选择所有名称。另一个将保持空白。

但是换行仍然不正确。但我认为你是如此专注于换行有点奇怪,因为它们在XML中并不重要。但也许你想要它,所以它更具可读性。

答案 1 :(得分:1)

模板的问题;

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

是:

  1. 它不会复制匹配的movie节点;和
  2. 它不加选择地应用模板 - 包括actor 孩子们也是分开处理的。
  3. 你应该做的是:

    <xsl:template match="/movie">
        <xsl:copy>
            <actor>
                <xsl:apply-templates select="actor/name"/>
             </actor>
            <xsl:apply-templates select="*[not(self::actor)]"/>
        </xsl:copy>
    </xsl:template>
    

    或者,如果你真的必须在其兄弟姐妹中保持actor的位置(为什么这很重要?):

    <xsl:template match="/movie">
        <xsl:copy>
            <xsl:apply-templates select="actor[1]/preceding-sibling::*"/>       
            <actor>
                <xsl:apply-templates select="actor/name"/>
             </actor>
            <xsl:apply-templates select="actor[last()]/following-sibling::*"/>
        </xsl:copy>
    </xsl:template>
    
      

    •没有换行符

    我无法使用您的代码重现此问题,但您应该将这两个放在样式表的顶层:

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    

    注意:

    正如我在您对您的问题的评论中已经提到的,这假设输出XML NOT 需要将其节点放在命名空间中 - 否则需要完成更多的工作。 / p>