选择条件为

时间:2015-06-17 16:26:05

标签: xml xslt rdf

我正在尝试转换XML文件,但我被阻止了。我们的想法是将<ore:Aggregation>节点中的每个元素聚合到下一个节点。这是某种逐项。但是每创建edm:WebResource我不能超过1 dc:item

XML:

<rdf:RDF>
    <ore:Aggregation rdf:about="id1">
        <some:crap/>
    </ore:Aggregation>
    <edm:ProvidedCHO rdf:about="id1">
        <some:crap/>
    </edm:ProvidedCHO>
    <edm:WebResource rdf:about="some/random/url"> 
        <some:crap/>
    </edm:WebResource>
            ...
               (n 'edm:WebResource' nodes)
            ...
    <edm:WebResource rdf:about="some/random/url">
        <some:crap/>    
    </edm:WebResource>

    <ore:Aggregation rdf:about="id2">
        <some:crap/>
    </ore:Aggregation>
    <edm:ProvidedCHO rdf:about="id2">
        <some:crap/>
    </edm:ProvidedCHO>
    <edm:WebResource rdf:about="some/random/url"> 
        <some:crap/>
    </edm:WebResource>
            ...
               (n 'edm:WebResource' nodes)
            ...
    <edm:WebResource rdf:about="some/random/url">
        <some:crap/>    
    </edm:WebResource>

        ... and on and on ...
</rdf:RDF>

XSL

<xsl:template match="/">
    <xsl:apply-templates select="/rdf:RDF/ore:Aggregation"/>
</xsl:template>

<xsl:template match="/rdf:RDF/ore:Aggregation">
    <rdf:RDF>
    <xsl:for-each select=".">
            <dc:item>
                <xsl:attribute name="rdf:about">
                    <xsl:value-of select="concat($fileName, '_item', position())"/>
                </xsl:attribute>

                <xsl:copy-of select="."/>
                <xsl:copy-of select="following-sibling::edm:ProvidedCHO[1]"/>
                <xsl:copy-of select="following-sibling::edm:WebResource[1]"/>

                <!-- WHERE IT SUCKS -->
                <xsl:if test="local-name(following-sibling::*[3]) = 'edm:WebResource'">
                    <xsl:copy-of select="following-sibling::*[3]"/>
                </xsl:if>                    
                <!-- ./WHERE IT SUCKS -->


            </dc:item>
    </xsl:for-each>
    </rdf:RDF>
</xsl:template>

另一种带来太多节点的尝试:

<!-- WHERE IT SUCKS -->
<xsl:copy-of select="following-sibling::*[local-name (preceding::*[1]) = 'ore:Aggregation']"/>
<!-- ./WHERE IT SUCKS -->

预期产出

<!-- ITEM N1 -->
<rdf:RDF>
    <dc:item rdf:about="some.concat.string"/>
    <ore:Aggregation rdf:about="id1">
        <some:crap/>
    </ore:Aggregation>
    <edm:ProvidedCHO rdf:about="id1">
        <some:crap/>
    </edm:ProvidedCHO>
    <edm:WebResource rdf:about="some/random/url"> 
        <some:crap/>
    </edm:WebResource>
</rdf:RDF>

<!-- ITEM N2 -->
<rdf:RDF>
     <dc:item rdf:about="some.concat.string"/>
     <ore:Aggregation rdf:about="id1">
     <etc/>

2 个答案:

答案 0 :(得分:2)

在XSLT 2.0中,这似乎是<?php $temp = $wp_query; $wp_query = null; $wp_query = new WP_Query(); $wp_query->query('showposts=24&post_type=movie&orderby=ASC' . '&paged=' . $paged); while ($wp_query->have_posts()) : $wp_query->the_post(); ?> 的工作(参见http://www.xml.com/pub/a/2003/11/05/tr.html)。特别是,将其与xsl:for-each-group

一起使用
group-starting-with

当定位在父 <xsl:for-each-group select="*" group-starting-with="ore:Aggregation"> 元素上时,这将完成,并将所有子元素排列成组,rdf:RDF是每个组的开头。 ore:Aggregration中的代码随后会为每个xsl:for-each-group元素调用一次,然后您可以使用ore:Aggregation函数访问该组中的所有元素。

尝试使用此XSLT作为初学者

current-group()

请注意,此生成的输出XML格式不正确,因为它缺少单个根元素。如果添加一个会更好,不仅仅是为了使其形成良好,但是命名空间声明也会在一个地方出现:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:rdf="rdf" xmlns:ore="ore" xmlns:dc="dc">
    <xsl:output method="xml" encoding="UTF-8" indent="yes" />

    <xsl:template match="rdf:RDF">
        <xsl:for-each-group select="*" group-starting-with="ore:Aggregation">
            <rdf:RDF xmlns:edm="edm" xmlns:ore="ore" xmlns:some="some">
                <dc:item rdf:about="{concat('item', position())}" />
                <xsl:apply-templates select="current-group()" />
            </rdf:RDF>
        </xsl:for-each-group>
    </xsl:template>

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

另请注意在创建<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:rdf="rdf" xmlns:ore="ore" xmlns:dc="dc"> <xsl:output method="xml" encoding="UTF-8" indent="yes" /> <xsl:template match="rdf:RDF"> <rdf:root xmlns:edm="edm" xmlns:ore="ore" xmlns:some="some"> <xsl:for-each-group select="*" group-starting-with="ore:Aggregation"> <rdf:RDF> <dc:item rdf:about="{concat('item', position())}" /> <xsl:apply-templates select="current-group()" /> </rdf:RDF> </xsl:for-each-group> </rdf:root> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet> 时使用Attribute Value Templates,这进一步减少了所需的代码量。

答案 1 :(得分:1)

我之前已经遇到过这种情况,而且我能够提出的最佳解决方案涉及设置操作。

在某种程度上这是有道理的,因为你想要在每个矿石之后的所有节点:聚合直到下一个矿石:聚合。

换句话说,您希望所有以下节点之外的下一个节点:聚合后面的所有内容。

值得庆幸的是,在XSLT 2.0中我们已经设置了操作运算符,因此我们不必跳过我们在XSLT 1.0中必须要做的复杂箍。

试试这个XPATH

following-sibling::node() except 
  (following-sibling::ore:Aggregation | 
   following-sibling::ore:Aggregation/following-sibling::node())

这应该为您提供您期望的节点集。

每次尝试将平面元素列表排序为某种结果结构时,此模式通常起作用。例如,我遇到的问题是找到具有特定属性的所有元素,然后将它们分组为一个。

因此,一般的解决方案是(伪代码)

如果我们可以同时指定终端标签及其兄弟姐妹,这会更简单一点,但这实际上并不太糟糕。

following-sibling::node() except 
  (following-sibling::{next-node-selection-criteria} | 
   following-sibling::{next-node-selection-criteria}/following-sibling::node())