我有以下XML结构:
<Article>
<id>1</id>
<line>L11</line>
<line>L12</line>
<line>L13</line>
</Article>
<Article>
<id>2</id>
<line>L21</line>
<line>L22</line>
<line>L23</line>
</Article>
我想使用XSLT一次迭代一篇文章的所有行,这样我就可以实现以下结构:(每篇文章都被转换成一个顺序,并且它的行被转换为新的行结构结构)
<orders>
<order>
<id>1</id>
<order_line>L11</order_line>
<order_line>L12</order_line>
<order_line>L13</order_line>
</order>
<order>
<id>2</id>
<order_line>L21</order_line>
<order_line>L22</order_line>
<order_line>L23</order_line>
</order>
</orders>
答案 0 :(得分:4)
使用XSLT,尝试将手头的任务视为一组必须匹配的模式或规则,以及每次遇到这种模式时要采取的操作。您通常可以让运行时担心循环等,以发现模式。
在您的具体情况中,您已经描述了两种您想要特殊逻辑的模式。每次有元素Article
时,您都希望应用规则将其名称更改为order
。
每当元素line
作为Article
的孩子遇到时,请将其替换为order_line
。对于任何其他模式,您只想复制原始文档中的内容:
<!-- Match element Article, and whenever it's encountered, insert an 'order' element, and copy the contents of Article -->
<xsl:template match="Article">
<order> <xsl:apply-templates/> </order>
</xsl:template>
<!-- Match element 'line', and whenever it's encountered, insert an 'order_line' element, and copy the contents -->
<xsl:template match="Article/line">
<order_line> <xsl:apply-templates/> </order_line>
</xsl:template>
<!-- Match any other element we haven't specified explicity, and copy it verbatim -->
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
答案 1 :(得分:3)
这是一个直接的转变:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/*">
<orders>
<xsl:apply-templates/>
</orders>
</xsl:template>
<xsl:template match="Article">
<order>
<xsl:apply-templates/>
</order>
</xsl:template>
<xsl:template match="line">
<order_line>
<xsl:apply-templates/>
</order_line>
</xsl:template>
<xsl:template match="id">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
编辑:一般根元素规则。
答案 2 :(得分:2)
这个完整的XSLT 1.0转换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<orders>
<xsl:apply-templates/>
</orders>
</xsl:template>
<xsl:template match="Article">
<order>
<xsl:apply-templates/>
</order>
</xsl:template>
<xsl:template match="line">
<order_line>
<xsl:apply-templates/>
</order_line>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档(包装到单个顶部元素中以使其格式正确):
<t>
<Article>
<id>1</id>
<line>L11</line>
<line>L12</line>
<line>L13</line>
</Article>
<Article>
<id>2</id>
<line>L21</line>
<line>L22</line>
<line>L23</line>
</Article>
</t>
会产生想要的正确结果:
<orders>
<order>
<id>1</id>
<order_line>L11</order_line>
<order_line>L12</order_line>
<order_line>L13</order_line>
</order>
<order>
<id>2</id>
<order_line>L21</order_line>
<order_line>L22</order_line>
<order_line>L23</order_line>
</order>
</orders>
<强>解释强>:
身份规则“按原样”复制每个节点。
标识规则由三个模板覆盖,每个模板与特定类型的元素(顶部元素Article
和line
)匹配,并简单地将元素重命名为: orders
,order
和order_line
。
答案 3 :(得分:1)
这只是我的头脑,但我认为你可以这样做:
<orders>
<xsl:for-each select="//Article">
<order>
<id><xsl:value-of select="./id"/></id>
<xsl:for-each select="./line">
<order_line><xsl:value-of select="child::text()" /></order_line>
</xsl:for-each>
</order>
</xsl:for-each>
</orders>
无论如何,它应该足以让你开始。但是在XSLT中只有for-each循环,没有用于计数器的循环。
答案 4 :(得分:0)
您的源XML文件格式不正确。为清楚起见,我的回答假定您已将其包装在元素中。这是一个非常简单的XML转换,所以我已经包含了一些注释,解释了每行代码的作用。
<!-- change the template match xpath to whatever the root xpath is in your document -->
<xsl:template match="root">
<orders>
<!-- loop over each Article -->
<xsl:for-each select="Article">
<order>
<!-- pass id through -->
<xsl:copy-of select="id"/>
<!-- loop over each line -->
<xsl:for-each select="line">
<!-- create an <order_line> node -->
<order_line>
<!-- get the value of the current <line> -->
<xsl:value-of select="."/>
</order_line>
</xsl:for-each>
</order>
</xsl:for-each>
</orders>
</xsl:template>
答案 5 :(得分:0)
在XSLT中执行“循环”的正确方法是让XSLT处理器为您遍历文档树。其他任何事情都在与XSLT的性质作斗争。
这是一个(接近)完整的解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<orders><xsl:apply-templates/></orders>
</xsl:template>
<xsl:template match="Article">
<order>
<id><xsl:value-of select="id"/></id>
<xsl:apply-templates select="line"/>
</order>
</xsl:template>
<xsl:template match="Article/line">
<order_line><xsl:value-of select="."/></order_line>
</xsl:template>
</xsl:stylesheet>
答案 6 :(得分:0)
试试这个,但我不是xslt专家:)
<?xml version="1.0" encoding="utf-8"?>
<xsl:template match="/" name="A">
<orders>
<xsl:for-each select="Articles/Article">
<order>
<id>
<xsl:value-of select="id" />
</id>
<xsl:for-each select="line">
<order_line>
<xsl:value-of select="node()"></xsl:value-of>
</order_line>
</xsl:for-each>
</order>
</xsl:for-each>
</orders>
</xsl:template>