使用子节点上的XSLT循环实现XML到XML的转换

使用子节点上的XSLT循环实现XML到XML的转换,xml,xslt,xsd,Xml,Xslt,Xsd,我刚刚开始学习XSLT,需要以下方面的帮助:- 以下是我的XML:- <?xml version="1.0" encoding="UTF-8"?> <FMPXMLRESULT> <METADATA> <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="Site_ID" TYPE="TEXT" /> <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="Road_Name" TY

我刚刚开始学习XSLT,需要以下方面的帮助:-

以下是我的XML:-

<?xml version="1.0" encoding="UTF-8"?>
<FMPXMLRESULT>
<METADATA>
  <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="Site_ID" TYPE="TEXT" />
  <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="Road_Name" TYPE="TEXT" />
  <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="KM" TYPE="NUMBER" />
</METADATA>
<RESULTSET FOUND="1">
  <ROW MODID="16" RECORDID="38664">
     <COL>
        <DATA>SI-3158</DATA>
     </COL>
     <COL>
        <DATA>Upper Taylor Main</DATA>
     </COL>
     <COL>
        <DATA>12.61</DATA>
     </COL>
  </ROW>
</RESULTSET>

SI-3158
上泰勒干管
12.61

在上面的XML中,第一个“字段”节点的值对应于第一个“数据”节点的值。我想用以下方式转换上面的XML

<?xml version="1.0"?>
<COLUMN>
 <NAME>Site_ID</NAME>
 <TYPE>TEXT</TYPE>
 <NULLABLE>YES</NULLABLE>
 <MAXREPEAT>1</MAXREPEAT>
 <VALUE>SI-3158</VALUE>
</COLUMN>
<COLUMN>
 <NAME>Road_Name</NAME>
 <TYPE>TEXT</TYPE>
 <NULLABLE>YES</NULLABLE>
 <MAXREPEAT>1</MAXREPEAT>
 <VALUE>Upper Taylor Main</VALUE>
</COLUMN>
<COLUMN>
 <NAME>KM</NAME>
 <TYPE>NUMBER</TYPE>
 <NULLABLE>YES</NULLABLE>
 <MAXREPEAT>1</MAXREPEAT>
 <VALUE>12.61</VALUE>
</COLUMN>

站点ID
正文
对
1.
SI-3158
道路名称
正文
对
1.
上泰勒干管
公里
数
对
1.
12.61
以下是我迄今为止所做的工作:-

<xsl:stylesheet version="1.0"       xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/FMPXMLRESULT/">
<xsl:for-each select="FIELD"> 
<COLUMN>
 <NAME><xsl:value-of select="@NAME"/></NAME>
 <TYPE><xsl:value-of select="@TYPE"/></TYPE>
 <NULLABLE><xsl:value-of select="@EMPTYOK"/></NULLABLE>
 <MAXREPEAT><xsl:value-of select="@MAXREPEAT"/></MAXREPEAT>
 <VALUE><xsl:value-of select="../../RESULTSET/ROW/COL/DATA"/></VALUE>
</COLUMN>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

使用XSLT,值第一个“数据”节点被添加到每个“字段”的“值”属性中,我需要在每个“COL”节点上循环

其次,我看到很多帖子都不推荐使用“xsl:for each”,所以有没有更好的方法来实现我的需求。提前感谢

试试这个:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="xml"/>
    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>
    <xsl:template match="METADATA/FIELD">
        <COLUMN>
            <NAME>
                <xsl:value-of select="@NAME"/>
            </NAME>
            <TYPE>
                <xsl:value-of select="@TYPE"/>
            </TYPE>
            <NULLABLE>
                <xsl:value-of select="@EMPTYOK"/>
            </NULLABLE>
            <MAXREPEAT>
                <xsl:value-of select="@MAXREPEAT"/>
            </MAXREPEAT>
            <xsl:variable name="position" select="position() div 2"/>
            <VALUE>
                <xsl:value-of select="//FMPXMLRESULT/RESULTSET/ROW/COL[$position]/DATA"/>
            </VALUE>
        </COLUMN>
    </xsl:template>
    <xsl:template match="RESULTSET"/>    
</xsl:stylesheet>


这将创建所需的结果。尽可能使用xsl:template而不是xsl:for each。

在尝试的样式表中,您需要更改:

<xsl:template match="/FMPXMLRESULT/">
<xsl:for-each select="FIELD"> 

致:


要使其按预期工作,除了值部分,需要通过其位置获取

请注意,结果不是格式良好的XML文档,因为它没有单个根元素


为此使用
xsl:for each
没有什么错。

是的,这要优雅得多。@Friedmann_bach,除了我错过了获取相应值的部分。。。。。。嗯,对。它对原始代码的“侵入性”更小。@DeepjyotMaher我没有看到您修改过的样式表,所以我无法判断它有什么问题。请参阅此处的工作示例:如果有多行怎么办?@michael.hor257k应该只有一行。谢谢你的提问。
<xsl:template match="/FMPXMLRESULT">
<xsl:for-each select="METADATA/FIELD">