首先,我使用一个收集管理软件GCStar来管理我的数字图书馆(漫画书/漫画/电影,你可以说-除了书籍之外,它非常棒)。问题是,它不允许我按多个键对架子进行排序,比如按系列和史诗编号排序。后来添加的剧集总是会在架子上显示得更低,按系列分组。
我对这些配置进行了修改,发现它使用的.gcs文件只不过是一个XML (我对它非常熟悉)。是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<collection type="GCTVepisodes" items="101" version="1.6.1">
<information>
<maxId>101</maxId>
</information>
<item
id="1"
name="The Vice President Doesn't Say Anything about the Possibility of
Him Being the Main Character"
series="Baccano"
season="1"
episode="1"
...
>
<synopsis>It's 1931 and...</synopsis>
...
</item>
<item ...
据我所知,这个程序总是通过ID (每当我添加一个插曲时增加)命令降序。因此,我需要对此进行一个转换,它将:
如何做到这一点(显然,这里不涉及剪切粘贴代码)?XSLT可以完成所有这些工作吗?我应该看看Perl中基于树的解析器吗?现在是周末,我在一台Linux机器上,所以在UNIX上运行的开源解决方案很好--用Perl最好。我该读些什么?
如果我不能在家里做这件事,那么,我总是可以在办公室设计一个小的数据传输工作,但是我真的很想要一个更简单的解决方案。
谢谢!:)
发布于 2011-07-08 22:06:56
maxId (和集合中的项)值不应更改,因为您没有删除或添加ids。
如果您想要一个简单的命令行,开放源码的XSLTProc,可以使用libxml2 2/libxslt中的XSLTProc。它几乎可以在每个标准linux上使用。http://xmlsoft.org/XSLT/xsltproc2.html
使用此命令xsltproc transform.xsl input.xml >output.xml
这里有一个解决方案,XSLT转换样式表,应该可以工作;-) (我有足够的空闲时间编写它)
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- Default: copy everything -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- remove items, they will be sorted and inserted later -->
<xsl:template match="/collection/item"/>
<!-- remove id -->
<xsl:template match="/collection/item/@id"/>
<xsl:template match="/collection">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<!-- copy and sort item by series, then season, then episode -->
<xsl:for-each select="item">
<xsl:sort select="@series" data-type="text"/>
<xsl:sort select="@season" data-type="number"/>
<xsl:sort select="@episode" data-type="number"/>
<xsl:copy>
<xsl:attribute name="id">
<xsl:value-of select="position()"/>
</xsl:attribute>
<!-- copy the rest of item -->
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我使用这些简化的数据来测试它:
<?xml version="1.0" encoding="UTF-8"?>
<collection type="GCTVepisodes" items="5" version="1.6.1">
<information>
<maxId>5</maxId>
</information>
<item
id="1"
name="The Vice President Doesn't Say Anything about the Possibility of
Him Being the Main Character"
series="Baccano"
season="1"
episode="1"/>
<item
id="2"
name="blabla"
series="c"
season="1"
episode="2"/>
<item
id="3"
name="abc"
series="Baccano"
season="2"
episode="1"/>
<item
id="4"
name="blabla2"
series="Baccano"
season="1"
episode="2"/>
<item
id="5"
name="first of c"
series="c"
season="1"
episode="1"/>
</collection>
这就是结果(看看位置和id是如何变化的):
<?xml version="1.0" encoding="UTF-8"?>
<collection type="GCTVepisodes" items="5" version="1.6.1">
<information>
<maxId>5</maxId>
</information>
<item id="1" name="The Vice President Doesn't Say Anything about the Possibility of Him Being the Main Character" series="Baccano" season="1" episode="1"/>
<item id="2" name="blabla2" series="Baccano" season="1" episode="2"/>
<item id="3" name="abc" series="Baccano" season="2" episode="1"/>
<item id="4" name="first of c" series="c" season="1" episode="1"/>
<item id="5" name="blabla" series="c" season="1" episode="2"/>
</collection>
发布于 2011-07-09 21:43:56
您可以使用两个简单的模板获得相同的结果:
item
元素进行排序。item
元素,并使用position()
函数重新计算id
属性。我们将保留所有其他后代节点的原样,但不包括item
的原始item
。用Saxon 6.5.5测试XSLT1.0转换
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()[not(self::item)]"/>
<xsl:apply-templates select="item">
<xsl:sort select="@series"/>
<xsl:sort select="@season" data-type="number"/>
<xsl:sort select="@episode" data-type="number"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="item">
<item id="{position()}">
<xsl:apply-templates select="@*[name()!='id']|node()"/>
</item>
</xsl:template>
</xsl:stylesheet>
当将上述转换应用于以下输入时(@therealmarv,稍微修改一下以包含子元素):
<collection type="GCTVepisodes" items="5" version="1.6.1">
<information>
<maxId>5</maxId>
</information>
<item
id="1"
name="The Vice President Doesn't Say Anything about the Possibility of
Him Being the Main Character"
series="Baccano"
season="1"
episode="1">
<synopsis>It's 1931 and...</synopsis>
</item>
<item
id="2"
name="blabla"
series="c"
season="1"
episode="2">
<synopsis>It's 1931 and...</synopsis>
</item>
<item
id="3"
name="abc"
series="Baccano"
season="2"
episode="1">
<synopsis>It's 1931 and...</synopsis>
</item>
<item
id="4"
name="blabla2"
series="Baccano"
season="1"
episode="2">
<synopsis>It's 1931 and...</synopsis>
</item>
<item
id="5"
name="first of c"
series="c"
season="1"
episode="1">
<synopsis>It's 1931 and...</synopsis>
</item>
</collection>
产生了下列产出:
<collection type="GCTVepisodes" items="5" version="1.6.1">
<information>
<maxId>5</maxId>
</information>
<item id="1" name="The Vice President Doesn't Say Anything about the Possibility of Him Being the Main Character" series="Baccano" season="1" episode="1">
<synopsis>It's 1931 and...</synopsis>
</item>
<item id="4" name="blabla2" series="Baccano" season="1" episode="2">
<synopsis>It's 1931 and...</synopsis>
</item>
<item id="3" name="abc" series="Baccano" season="2" episode="1">
<synopsis>It's 1931 and...</synopsis>
</item>
<item id="5" name="first of c" series="c" season="1" episode="1">
<synopsis>It's 1931 and...</synopsis>
</item>
<item id="2" name="blabla" series="c" season="1" episode="2">
<synopsis>It's 1931 and...</synopsis>
</item>
</collection>
发布于 2011-07-08 21:46:41
XSLT可以完成所有这些工作吗?
是。见下面的分答案。
是的,您可以使用XSLT对XML进行排序。
sort.asp
您也可以使用它来编写任何您想要的文本。这意味着您可以在转换中替换数据。
它还可以赋值变量、if语句、环、do XPath查询、有内置函数库等等,所以它将足够强大到您想要做的事情。
...Which还意味着您可以使用它来编写XML。
我该读些什么?
XSLT :)
w3schools链接(上面的所有链接)对我来说已经够多了,但是我已经对XML (属性、元素、根元素、内部文本等等)很熟悉了。如果您熟悉这一点,只需阅读XSLT。
您还可以查看XmlStarlet,它是一个用于从命令行或shell脚本/批处理文件中查询和转换XML的工具(尽管对于转换,它可能使用XSLT )。
https://stackoverflow.com/questions/6630787
复制相似问题