如何XSLT转换XML嵌套属性元素并连接名称

时间:2015-06-11 16:44:11

标签: xml xslt transformation pubmed

我根本不熟悉XML / XSLT。我只是想学习足够的知识,将这个XML文件转换成我的Access数据库可以使用的东西。 XML数据以属性格式输出,Access仅喜欢元素格式。我有基本的转换,但我似乎无法对嵌套数据进行优化。

我希望最终结果是所有元素。目前,我的XSLT脚本试图在子元素的名称中包含parental name属性,但这可能不是必需的。如果我可以在其名称中编号列表元素,那将是非常棒的。例如“AuthorList1”,“AuthorList2”或“Author1”,“Author2”。

这是我正在处理的XML(缩写):

XML

<Result>
<DocSum>
<Id>25587056</Id>
<Item Name="PubDate" Type="Date">2015 Jan 13</Item>
<Item Name="EPubDate" Type="Date">2015 Jan 13</Item>
<Item Name="Source" Type="String">Invest Ophthalmol Vis Sci</Item>
<Item Name="AuthorList" Type="List">
    <Item Name="Author" Type="String">Wang Q</Item>
    <Item Name="Author" Type="String">Tuten WS</Item>
    <Item Name="Author" Type="String">Lujan BJ</Item>
</Item>
<Item Name="Title" Type="String">Adaptive optics microperimetry</Item>
<Item Name="Volume" Type="String">56</Item>
<Item Name="ArticleIds" Type="List">
    <Item Name="pubmed" Type="String">25587056</Item>
    <Item Name="pii" Type="String">iovs.14-15576</Item>
    <Item Name="doi" Type="String">10.1167/iovs.14-15576</Item>
</Item>
<Item Name="References" Type="List"></Item>
<Item Name="HasAbstract" Type="Integer">1</Item>
</DocSum>
</Result

我在XSLT上已经走得很远了,但我并不是一直都在那里。一个不断出现的问题是空元素(如引用)获取不允许的空名称。当我使用“Item [@Type ='List']”的匹配模式尝试命令时发生这种情况。另外,我似乎无法让列表的子节点(元素?)成为它们自己的元素。

XSLT

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

<xsl:template match="@*" >
    <xsl:element name="{name()}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

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

<xsl:template match="Item">
    <xsl:element name="{@Name}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

<xsl:template match="child::Item">
    <xsl:variable name="Parent" select="TEST"/>
        <xsl:element name="{$Parent}{@Name}">
            <xsl:value-of select="."/>
        </xsl:element>
</xsl:template>
</xsl:stylesheet>

我希望这有点道理。我真的不想成为这方面的专家,因为我怀疑我将在很长一段时间内再次处理XML转换。我很感激即将到来的任何帮助。

1 个答案:

答案 0 :(得分:0)

您遇到的一个问题是匹配Item

的模板
<xsl:template match="Item">
    <xsl:element name="{@Name}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

通过在此使用xsl:value-of,它不会继续处理任何子节点,因此您不会在任何子Item元素上进行任何匹配。您需要在此处使用xsl:apply-templates,以允许模板应用于孩子

<xsl:template match="Item">
    <xsl:element name="{@Name}">
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

另一个问题是与child::Item匹配的其他模板。我认为这也会与父Item元素匹配,因此实际上与其他Item模板具有相同的优先级。您可能需要将匹配替换为:

<xsl:template match="Item[@Type='List']/Item">

最后,您在此模板中定义Parent变量,如下所示:

<xsl:variable name="Parent" select="TEST"/>

这会将Parent设置为名为TEST的元素的值,或许您只想要“Test”的文字值。所以,你应该这样定义

<xsl:variable name="Parent" select="'TEST'"/>

试试这个XSLT

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

<xsl:template match="@*" >
    <xsl:element name="{name()}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

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

<xsl:template match="Item">
    <xsl:element name="{@Name}">
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

<xsl:template match="Item[@Type='List']/Item">
    <xsl:variable name="Parent" select="'TEST'"/>
        <xsl:element name="{$Parent}{@Name}">
            <xsl:value-of select="."/>
        </xsl:element>
</xsl:template>
</xsl:stylesheet>