1

我有一个 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 中有重复的命名属性,但我不知道如何以编程方式使用引用源中元素的唯一组合创建属性名称。

4

2 回答 2

0

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

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

然后:您没有从rows(或其后代)的孙辈那里获得任何属性,因为您xsl:for-each迭代的是孩子,而不是后代。您可以将 for-each 重写为应用模板,可能使用一种模式(这将使其易于递归,并且某些 XSLT 程序员会发现它更惯用),或者您可以更改select="*""select="descendant::*".

于 2012-09-22T21:14:30.773 回答
0

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

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

于 2012-09-23T07:33:39.827 回答