嵌套属性的XSL转换

时间:2016-02-06 19:15:46

标签: xml xslt filemaker

我的任务是将Text和任何相关的Font Attributes从以下(简化的)示例XML中剥离到FileMaker数据库中。示例XML:

<Font Id="Arial" Script="normal" Size="32" Underlined="no" Italic="no" Weight="normal">
    <Paragraph>
        <Text>This <Font Italic="yes">word</Font> is italic</Text>
        <Text>This entire line has no formatting</Text>
        <Text>This<Font Italic="yes">line</Font><Font Underlined="yes" Italic = "yes"> has multiple formats</Font></Text>
    </Paragraph>

    <Paragraph>
        <Text>This is the first line of the second paragraph and has no formatting</Text>
        <Text>This line also has no formatting</Text>
        <Text><Font Underlined="yes">This entire line is underlined</Font></Text>
    </Paragraph>
</Font>

如您所见,<Paragraph>元素由`节点包围。 (我希望我正确地指这些部分)。我已成功编写代码,以便在存在NO嵌套Font属性时将单个FULL行文本与嵌套Font属性一起传输到数据库中,或者嵌套Font属性包含整个文本数据。 我所坚持的是如何处理在文本数据中嵌套属性的文本行,例如第一段中的第一行和第一段中的第三行。

我要做的是捕获每个数据片段及其属性。我的架构允许每行文本(a,b,c)最多三个嵌套的Font属性。使用示例XML文件,我的FileMaker数据库对于段落1应该如此(简化):

Record 1
Line 1a Text: This
Line 1a Italic: (no value)
Line 1a Underlined: (no value)

Line 1b Text: word
Line 1b Italic: yes
Line 1b Underlined: (no value)

Line 1c Text: is italic
Line 1c Italic: (no value)
Line 1c Underlined: (no value)

Line 2a Text: This entire line has no formatting
Line 2a Italic: (no value)
Line 2a Underlined: (no value)

Line 2b Text: (no value)
Line 2b Italic:  (no value)
Line 2b Underlined: (no value)

Line 2c Text: (no value)
Line 2c Italic: (no value)
Line 2c Underlined: (no value)

Line 3a Text: This
Line 3a Italic: (no value)
Line 3a Underlined: (no value)

Line 3b Text: line
Line 3b Italic: yes
Line 3b Underlined: (no value)

Line 3c Text: has multiple formats
Line 3c Italic: yes
Line 3c Underlined: yes

当然,我无法预测何时何地应用格式。我希望我已经清楚了,并且事先感谢你提供的任何指示,以帮助我完成这项任务。

1 个答案:

答案 0 :(得分:1)

我建议你尝试这样的事情,至少作为你的出发点:

<强> XSLT

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

<xsl:template match="/Font">
    <FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
        <METADATA>
            <FIELD NAME="Text"/>
            <FIELD NAME="IsItalic" TYPE="NUMBER"/>
            <FIELD NAME="IsUnderline" TYPE="TEXT"/>
            <FIELD NAME="Paragraph" TYPE="TEXT"/>
        </METADATA>
        <RESULTSET>
            <!-- create a record for each text node, descendant of Paragraph -->
            <xsl:for-each select="Paragraph//text()">
                <ROW>
                    <!-- get the value of the current text node itself  -->
                    <COL><DATA><xsl:value-of select="."/></DATA></COL>
                    <!-- get the value of @Italic from the nearest ancestor that has such attribute -->
                    <COL><DATA><xsl:value-of select="ancestor::*[@Italic][1]/@Italic"/></DATA></COL>
                    <!-- get the value of @Underlined from the nearest ancestor that has such attribute -->
                    <COL><DATA><xsl:value-of select="ancestor::*[@Underlined][1]/@Underlined"/></DATA></COL>
                    <!-- get the ID of the ancestor Paragraph -->
                    <COL><DATA><xsl:value-of select="generate-id(ancestor::Paragraph)"/></DATA></COL>
                </ROW>
            </xsl:for-each>
        </RESULTSET>
    </FMPXMLRESULT>
</xsl:template>

</xsl:stylesheet>

应用于您的输入示例,您将获得:

enter image description here

请注意,段落ID仅在当前转换的范围内是唯一的,而不是普遍的。

加了:

根据我更好的判断,这是一个样式表,它将为每个Paragraph创建一个记录,每个记录是3行3个文本节点的严格网格。

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

<xsl:template match="/Font">
    <FMPXMLRESULT>
        <METADATA>
            <FIELD NAME="Line 1a Text"/>
            <FIELD NAME="Line 1a Italic"/>
            <FIELD NAME="Line 1a Underlined"/>

            <FIELD NAME="Line 1b Text"/>
            <FIELD NAME="Line 1b Italic"/>
            <FIELD NAME="Line 1b Underlined"/>

            <FIELD NAME="Line 1c Text"/>
            <FIELD NAME="Line 1c Italic"/>
            <FIELD NAME="Line 1c Underlined"/>

            <FIELD NAME="Line 2a Text"/>
            <FIELD NAME="Line 2a Italic"/>
            <FIELD NAME="Line 2a Underlined"/>
            <FIELD NAME="Line 2b Text"/>
            <FIELD NAME="Line 2b Italic"/>
            <FIELD NAME="Line 2b Underlined"/>

            <FIELD NAME="Line 2c Text"/>
            <FIELD NAME="Line 2c Italic"/>
            <FIELD NAME="Line 2c Underlined"/>

            <FIELD NAME="Line 3a Text"/>
            <FIELD NAME="Line 3a Italic"/>
            <FIELD NAME="Line 3a Underlined"/>

            <FIELD NAME="Line 3b Text"/>
            <FIELD NAME="Line 3b Italic"/>
            <FIELD NAME="Line 3b Underlined"/>

            <FIELD NAME="Line 3c Text"/>
            <FIELD NAME="Line 3c Italic"/>
            <FIELD NAME="Line 3c Underlined"/>
        </METADATA>
        <RESULTSET>
            <!-- create a record for each Paragraph -->
            <xsl:for-each select="Paragraph">
                <ROW>
                    <!-- for each line ...  -->
                    <xsl:for-each select="Text">
                        <xsl:variable name="text-nodes" select=".//text()" />
                        <!-- process the first three text nodes  -->
                        <xsl:call-template name="create-cells">
                            <xsl:with-param name="text-node" select="$text-nodes[1]"/>
                        </xsl:call-template>
                        <xsl:call-template name="create-cells">
                            <xsl:with-param name="text-node" select="$text-nodes[2]"/>
                        </xsl:call-template>
                        <xsl:call-template name="create-cells">
                            <xsl:with-param name="text-node" select="$text-nodes[3]"/>
                        </xsl:call-template>
                    </xsl:for-each> 
                </ROW>
            </xsl:for-each>
        </RESULTSET>
    </FMPXMLRESULT>
</xsl:template>

<xsl:template name="create-cells">
    <xsl:param name="text-node"/>
    <!-- get the value of the text node itself  -->
    <COL><DATA><xsl:value-of select="$text-node"/></DATA></COL>
    <!-- get the value of @Italic from the nearest ancestor that has such attribute -->
    <COL><DATA><xsl:value-of select="$text-node/ancestor::*[@Italic][1]/@Italic"/></DATA></COL>
    <!-- get the value of @Underlined from the nearest ancestor that has such attribute -->
    <COL><DATA><xsl:value-of select="$text-node/ancestor::*[@Underlined][1]/@Underlined"/></DATA></COL>
</xsl:template>

</xsl:stylesheet>

结果看起来像这样(列表视图中显示两条记录):

enter image description here