XSL-T适用于属性名称中重复的所有子元素中的所有属性

时间:2012-09-22 21:01:50

标签: xml xslt duplicates

我有一个XSL-T,它循环遍历XML的所有子元素,并将这些属性推送到单个输出元素中。但是,这些子元素中存在重复的属性(多个子元素中的属性相同),并且XSL仅为每个元素提供一个结果(系列中该属性中只有一个值)。我也不相信它正在寻找孩子们的所有孩子,并正确地将这些孩子推入到结果属性集中。

我尝试过使用单个动态XSL-T,并使用N#XSL模板,每个模板都专注于单个子元素,然后将子元素的名称硬编码到输出属性中 - 第二个方法只给出第一个模板的结果,所以没有解决我的问题。如果我的第二种方法可以修复工作,那很好。如果有一种方法以动态方式(第一个选项)以编程方式执行此操作,那么真的很酷! XSL很强大,所以希望它可以做到这一点,你们都可以提供帮助!

下面是一个形状像我的XML文档的例子:

<JSON offset="0" total_rows="1337" millis="987">
<rows Attribute1="" Attribute2="" oid="0000001">
<Name Attribute1="FirstName" Attribute2="LastName">
<_id oid="1337"/>
</Name>
<Occupation oid="12345"/>
</rows>
</JSON>

请注意,父元素和子元素之间存在重复的属性。我只能使用动态代码或硬编码方法获得一组这些属性。此外,我不确定这两种方法是否成功地试图让孩子成为行的孩子 - 因为他们没有工作,我无法确认。

我的两个XSL方法:

动态(仅为重复的属性返回一个值):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="JSON">
<DATAPARENT>
<xsl:apply-templates/>
</DATAPARENT>
</xsl:template>
<xsl:template match="//rows">

        <xsl:element name="DataRow">
        <xsl:for-each select="*">                   

                    <xsl:for-each select="@*">  

                    <xsl:attribute name="{name()}">  

                        <xsl:value-of select="." />  

                    </xsl:attribute>

                    </xsl:for-each> 

        </xsl:for-each>
        </xsl:element>
        <xsl:text>&#10;</xsl:text>


</xsl:template>
</xsl:stylesheet>

硬编码(不太灵活,这很好,但除了第一组带有rows_ {name()}的结果外,我也没有给我任何东西):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="JSON">
<DATAPARENT>
<xsl:apply-templates/>
</DATAPARENT>
</xsl:template>

<xsl:template match="/rows">

        <xsl:element name="DataRow">            

                    <xsl:for-each select="@*">  

                    <xsl:attribute name="rows_{name()}">  

                        <xsl:value-of select="." />  


                    </xsl:attribute>

                    </xsl:for-each> 

        </xsl:element>  

</xsl:template>

<xsl:template match="//Name">

        <xsl:element name="DataRow">            

                    <xsl:for-each select="@*">  

                    <xsl:attribute name="Name_{name()}">  

                        <xsl:value-of select="." />  


                    </xsl:attribute>

                    </xsl:for-each> 

        </xsl:element>  

</xsl:template>

<xsl:template match="//Occupation">

        <xsl:element name="DataRow">            

                    <xsl:for-each select="@*">  

                    <xsl:attribute name="Occupation_{name()}">  

                        <xsl:value-of select="." />  


                    </xsl:attribute>

                    </xsl:for-each> 

        </xsl:element>  

</xsl:template>

</xsl:stylesheet>

感谢大家提供的建议和见解。在建议仅执行元素属性循环的基本方法之前,请查看我已经提供的XSL;我已经在使用它们了,这是我没有解决的重复属性问题。谢谢!

**编辑:所需的输出为:

<DATAPARENT>
<DataRow rows_Attribute1="" rows_Attribute2="" rows_oid="0000001" Name_Attribute1="FirstName" Name_Attribute2="LastName" Name__id_oid="1337" Occupation_oid="12345" />
<DataRow rows_Attribute1="1" rows_Attribute2="2" rows_oid="0000002" Name_Attribute1="FirstName" Name_Attribute2="LastName" Name__id_oid="1254" Occupation_oid="99231" />
</DATAPARENT>**

我知道我不能在XML中使用重复的命名属性,但我不知道如何使用引用源中元素的唯一组合以编程方式创建属性名称。

2 个答案:

答案 0 :(得分:0)

首先:在您的第一个示例中,您将rows的所有子项的所有属性写为一个DataRow元素上具有相同名称的属性。您只获得具有任何给定名称的一个属性(即使子项中出现多个具有该名称的属性),因为XML仅允许元素上具有任何给定名称的一个属性。您的输出DataRows元素可以有一个oid属性,但如果样式表要生成XML输出,则它不能有两个属性。

如果您希望子树中的每个属性 - 值对都有一个名称 - 值对,请将它们写为DataRow的子项,而不是属性。

然后:你没有得到rows(或他们的后代)的孙子的任何属性,因为你的xsl:for-each遍历了孩子,而不是后代。您可以将for-each重写为apply-templates,可能使用某种模式(这样可以很容易地重复出现以及某些XSLT程序员会发现哪些更惯用),或者您可以将select="*"更改为{{1} }。

答案 1 :(得分:0)

哟没有显示你想要的输出,但它看起来好像你正在尝试创建一个具有多个同名属性的元素。这在XML中是不允许的,因此XSLT不允许它。

如果您尝试将两个具有相同名称的属性添加到同一元素,则XSLT会添加最后一个; XQuery报告错误。

相关问题