xsl根据父属性的匹配在preibling parent下移动节点

时间:2018-02-07 20:51:28

标签: xslt

我正在尝试以某种格式处理从pdf转换为另一个xml文件的xml。首先,我想根据文本的几何图形将一些文本/节点移动/分组,但未能这样做。以下是我的输入&我想要的是什么:

输入xml:

part_func

输出xml:

<Pages>
    <Page>
        <PAGENUMBER>1</PAGENUMBER>
        <Box llx="59.40" lly="560.64" urx="68.58" ury="571.68">
            <Text>5.</Text>
        </Box>
        <Box llx="81.84" lly="560.64" urx="194.39" ury="571.68">
           <Text>Equipment list</Text>
        </Box>
        <Box llx="257.40" lly="560.64" urx="265.36" ury="571.68">
            <Text>C</Text>
        </Box>
        <Box llx="315.84" lly="535.32" urx="325.63" ury="546.36">
            <Text>a)</Text>
        </Box>
    </Page>
    <Page>
         same structure as above...
    </Page>
</Pages>

我有什么:          

<Pages>
    <Page>
        <PAGENUMBER>1</PAGENUMBER>
        <Box llx="59.40" lly="560.64" urx="68.58" ury="571.68">
            <Text>5. Equipment list C</Text>
        </Box>
        <Box llx="315.84" lly="535.32" urx="325.63" ury="546.36">
            <Text>a)</Text>
        </Box>
    </Page>
    <Page>
         same structure as above...
    </Page>
</Pages>

1.它不复制有用节点2.我不知道如何排除以下节点。我希望有人可以帮助我。非常感谢提前。

我尝试了以下操作来排除重复项,但它不会复制我想要的内容:

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

<xsl:template match="Box">
    <xsl:choose>
        <xsl:when test="@ury = following-sibling::Box/@ury">
            <xsl:call-template name="identity"/>
            <xsl:apply-templates select ="@*"/>
            <xsl:copy-of select="following-sibling::Box/Text"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy>
                <xsl:apply-templates/>
            </xsl:copy>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

1 个答案:

答案 0 :(得分:1)

这是muenchian grouping的情况,您需要根据某些通用条件对节点进行分组,并对它们进行处理以提供输出。

根据所使用的XSLT版本,XSLT 1.0和XSLT 2.0的解决方案不同

XSLT 1.0

1.0版使用<xsl:key>根据通用标准对元素进行分组。在这种情况下,分组是基于属性@ury的值完成的,因此我们定义了一个键

<xsl:key name="groupingKey" match="Box" use="@ury" />

使用此键,模板被组合在一起进行处理。

<xsl:template match="Box[generate-id() = generate-id(key('groupingKey', @ury)[1])]">

最后在分组元素中,在<Text>元素上运行循环以连接其值。

<Text>
    <xsl:variable name="fullText">
        <xsl:for-each select="key('groupingKey', @ury)/Text">
            <xsl:value-of select="concat(., ' ')" />
        </xsl:for-each>
    </xsl:variable>
    <xsl:value-of select="normalize-space($fullText)" />
</Text>

以下是完整的XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:strip-space elements="*" />

    <xsl:key name="groupingKey" match="Box" use="@ury" />

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

    <xsl:template match="Box[generate-id() = generate-id(key('groupingKey', @ury)[1])]">
        <xsl:copy>
            <xsl:apply-templates select="@*" />
            <Text>
                <xsl:variable name="fullText">
                    <xsl:for-each select="key('groupingKey', @ury)/Text">
                        <xsl:value-of select="concat(., ' ')" />
                    </xsl:for-each>
                </xsl:variable>
                <xsl:value-of select="normalize-space($fullText)" />
            </Text>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Box" />
</xsl:stylesheet>

XSLT 2.0

与XSLT 1.0相比,2.0版是先进的,并提供了一种更简单的方法。 <xsl:for-each-group>group-by功能可用于将元素组合在一起。

<xsl:for-each-group select="Box" group-by="@ury">

以下是完整的XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:output method="xml" indent="yes" />

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

    <xsl:template match="Page">
        <xsl:copy>
            <xsl:apply-templates select="PAGENUMBER" />
            <xsl:for-each-group select="Box" group-by="@ury">
                <xsl:copy>
                    <xsl:apply-templates select="@*" />
                    <Text>
                        <xsl:variable name="fullText">
                            <xsl:for-each select="current-group()/Text">
                                <xsl:value-of select="concat(., ' ')" />
                            </xsl:for-each>
                        </xsl:variable>
                        <xsl:value-of select="normalize-space($fullText)" />
                    </Text>
                </xsl:copy>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

XSLT都提供了所需的输出

<Pages>
    <Page>
        <PAGENUMBER>1</PAGENUMBER>
        <Box llx="59.40" lly="560.64" urx="68.58" ury="571.68">
            <Text>5. Equipment list C</Text>
        </Box>
        <Box llx="315.84" lly="535.32" urx="325.63" ury="546.36">
            <Text>a)</Text>
        </Box>
    </Page>
</Pages>