2012-02-24 108 views
1

我想用XSLT进行转换。这是我的XML数据源:罕见的XSLT转换

<Memoria> 
    <seccion> 
    <contenido><p>TEXT</p> 
    <ul> 
     <li>LIST</li> 
    </ul> 
    <p>ANOTHER TEXT</p> 
    <p>&amp;nbsp;</p></contenido> 
    </seccion>  
</Memoria> 

我试图使用XSLT这样的:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output method="xml" indent="yes"/> 
<xsl:template match="/Memoria"> 
<cosa> 
    <xsl:for-each select="seccion"> 
    <Address> 
    <xsl:for-each select="contenido"> 
    <FirstName><xsl:value-of select="p" /></FirstName> 
    </xsl:for-each> 
    <ul> 
     <LastName><xsl:value-of select="ul/li" /></LastName> 
    </ul> 
    </Address> 
    </xsl:for-each> 
</cosa> 
</xsl:template> 

</xsl:stylesheet> 

而得到这样的:

<?xml version="1.0"?> 
<cosa> 
    <Address> 
    <FirstName>TEXT</FirstName> 
    <ul> 
     <LastName>LIST</LastName> 
    </ul> 
    </Address> 
</cosa> 

但我相信:

<?xml version="1.0"?> 
<cosa> 
    <Address> 
    <FirstName>TEXT</FirstName> 
    <ul> 
     <LastName>LISTr</LastName> 
    </ul> 
    <FirstName>ANOTHER TEXT</FirstName> 
    </Address> 
</cosa> 

我从外部应用程序获取这个XML。

+2

我不知道什么是 “罕见” 这个问题。 – 2012-02-24 22:03:50

+0

可能是因为他很少使用XSL转换..;) – 2012-02-25 08:36:15

回答

0

xsl:value-of将获取节点集中第一个元素的内容。如果您想操作集合中的所有元素,则需要xsl:for-eachxsl:apply-templates。但是,如果你这样做,你会得到:

<?xml version="1.0"?> 
<cosa> 
    <Address> 
    <FirstName>TEXT</FirstName> 
    <ul> 
     <LastName>LISTr</LastName> 
    </ul> 
    <FirstName>ANOTHER TEXT</FirstName> 
    <FirstName>&amp;&nbsp;</FirstName> 
    </Address> 
</cosa> 
0

假设你肯定知道,你永远有名字的第一个P元素,和第二名字在第二个P元素,你可以使用一个共同的节点集()函数来获取里面的特定元素的for-each循环:

以下修改XSLT生成所需的输出,你已经把你的问题:

<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:exsl="http://exslt.org/common"> 

    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/Memoria"> 
    <cosa> 
     <xsl:for-each select="seccion"> 
     <Address> 
      <xsl:for-each select="contenido"> 
      <FirstName> 
       <xsl:value-of select="p" /> 
      </FirstName> 
      <ul> 
       <LastName> 
       <xsl:value-of select="ul/li" /> 
       </LastName> 
      </ul> 
      <FirstName> 
       <xsl:value-of select="exsl:node-set(.)/p[2]/."/> 
      </FirstName> 
      </xsl:for-each> 
     </Address> 
     </xsl:for-each> 
    </cosa> 
    </xsl:template> 

</xsl:stylesheet> 

注:我通常使用的xmlns :msxsl =“urn:schemas-microsoft-com:xslt”用于node-set()函数,但我认为exsl不是供应商特定的:)

如果您的XML结构不一致或可预测,这很可能会中断;否则它将起作用,并且不需要另一个for-each来获取第二个FirstName结果元素的第二个P元素。

我希望这有帮助!

+0

我会尝试这个,因为我的代码是可变的如果ul标签不存在,我可以做同样的事情吗?谢谢 – user1075738 2012-02-25 10:50:58

+0

如果存在,可以使用xsl:if test语法添加条件来拉取ul标签。 – 2012-02-25 14:16:41

1

我不知道究竟要达到什么......但是,下面的XSLT:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/Memoria"> 
     <cosa> 
      <xsl:for-each select="seccion"> 
       <Address> 
        <xsl:apply-templates select="contenido" /> 
       </Address> 
      </xsl:for-each> 
     </cosa> 
    </xsl:template> 

    <xsl:template match="contenido"> 
     <xsl:apply-templates select="p | ul" /> 
    </xsl:template> 

    <xsl:template match="p"> 
     <FirstName> 
      <xsl:value-of select="text()"/> 
     </FirstName> 
    </xsl:template> 

    <xsl:template match="ul"> 
     <ul> 
      <LastName> 
       <xsl:value-of select="li"/> 
      </LastName> 
     </ul> 
    </xsl:template> 

</xsl:stylesheet> 

将产生以下的输出:

<?xml version="1.0" encoding="UTF-8"?> 
<cosa> 
    <Address> 
     <FirstName>TEXT</FirstName> 
     <ul> 
      <LastName>LIST</LastName> 
     </ul> 
     <FirstName>ANOTHER TEXT</FirstName> 
     <FirstName>&amp;nbsp;</FirstName> 
    </Address> 
</cosa> 

现在你可能认为加入的条件,以排除&amp;&nbsp;元件从输出:

<xsl:template match="p"> 
    <xsl:if test="not(contains(text(), '&amp;'))"> 
    <FirstName> 
     <xsl:value-of select="text()"/> 
    </FirstName> 
    </xsl:if> 
</xsl:template> 
3

难得的转型?提供了一个合适的输入XML和期望的输出,它不会在XSLT中罕见..
老实说,我不满意您的示例输入和输出XML。我想出了一个XML希望这就是你的XML的样子。如果不是,则调出精确的I/P和O/P XML。

<?xml version="1.0" encoding="utf-8"?> 
<Memoria> 
    <seccion> 
    <contenido> 
     <p>TEXT</p> 
     <ul> 
     <li>Item1</li> 
     <li>Item2</li> 
     <li>Item3</li> 
     </ul> 
     <p>ANOTHER TEXT</p> 
     <ul> 
     <li>Itema</li> 
     <li>Itemb</li> 
     <li>Itemc</li> 
     </ul> 
    </contenido> 
    </seccion> 
</Memoria> 

通讯XSLT代码:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
    <cosa> 
     <xsl:apply-templates select="//contenido"/> 
    </cosa> 
    </xsl:template> 

    <xsl:template match="text()"/> 

    <xsl:template match="contenido"> 
    <Address> 
     <xsl:apply-templates select="p|ul"/> 
    </Address> 
    </xsl:template> 

    <xsl:template match="p[not(contains(.,'&amp;'))]"> 
    <FirstName> 
     <xsl:value-of select="."/> 
    </FirstName> 
    </xsl:template> 

    <xsl:template match="ul"> 
    <ul> 
     <xsl:for-each select="li"> 
    <LastName> 
     <xsl:value-of select="."/> 
    </LastName> 
     </xsl:for-each> 
    </ul> 
    </xsl:template> 

</xsl:stylesheet> 
+0

谢谢,我错误地使用了模板,但是你的代码很好地解释了它是如何工作的。 – user1075738 2012-02-25 10:49:05

+0

@ user1075738,除了我粗鲁的话之前:)很高兴知道我可以帮忙(Y) – 2012-02-25 18:25:10