我想将与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...
有些事情不能像想要的那样工作:
任何帮助都将不胜感激。
答案 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>
是:
movie
节点;和actor
孩子们也是分开处理的。你应该做的是:
<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>