XSLT元素名称作为字符串
我想类似下面的使用XSLT输出的东西XSLT元素名称作为字符串
XML:
<myroot>
<node1>
<subnode1>somestuff</subnode1>
<subnode2>otherstuff</subnode2>
</node1>
<node2>
<subnode2></subnode2>
<subnode3>stuff here</subnode3>
</node2>
<node3>
<subnode>stuff</subnode>
<subnode>stuff</subnode>
<subnode>other</subnode>
</node3>
</myroot>
在哪里,我不知道一个给定的实例节点名称。
我希望我的输出看起来像这样:
myroot = new jsonObject();
myroot.node1 = new jsonObject();
myroot.node1.subnode1 = "holder";
myroot.node1.subnode2 = "holder";
myroot.node2 = new jsonObject();
myroot.node2.subnode2 = "holder";
myroot.node2.subnode3 = "holder";
myroot.node3 = new jsonObject();
myroot.node3.subnode = new array();
"arraystart"
myroot.node3.subnode[aindex] = new jsonObject();
myroot.node3.subnode[aindex] = "holder";
"endarray"
要点:
- = “持有人”;可以是任何东西独一无二的,因为我将稍后对此进行更改
- “arraystart”和“endarray”可以是任何 独一无二的,因为我会改变这 后来
- 我不知道具体的节点名称 超越了根。
- 我不知道树 (6-7一些深存在)
- 我不知道号码或位置 或数组元素的深度,但孩子 节点(元素)是同一名称那些团体。
- 可能存在多个阵列,并且 可能处于任何树深度。
- 元素文本没有子 节点
这个样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="name" match="*" use="name()"/>
<xsl:template match="text()"/>
<xsl:template match="*[*]">
<xsl:param name="name"/>
<xsl:value-of select="concat($name,
name(),
' = new jsonObject();
')"/>
<xsl:apply-templates>
<xsl:with-param name="name" select="concat($name,name(),'.')"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*[not(*)][count(../*|key('name',name()))!=count(key('name',name()))]">
<xsl:param name="name"/>
<xsl:value-of select="concat($name,
name(),
' = "holder";
')"/>
</xsl:template>
<xsl:template match="*[not(*)][1][count(../*|key('name',name()))=count(key('name',name()))]" priority="1">
<xsl:param name="name"/>
<xsl:value-of select="concat($name,
name(),
' = new array();
',
'"arraystart"
')"/>
<xsl:apply-templates select="following-sibling::*" mode="array">
<xsl:with-param name="name" select="concat($name,name(),'.')"/>
</xsl:apply-templates>
<xsl:text>"endarray"</xsl:text>
</xsl:template>
<xsl:template match="*" mode="array">
<xsl:param name="name"/>
<xsl:value-of select="concat($name,
'[aindex] = ')"/>
<xsl:choose>
<xsl:when test="contains(.,'stuff')">new jsonObject();
</xsl:when>
<xsl:otherwise>"holder";
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
输出:
myroot = new jsonObject();
myroot.node1 = new jsonObject();
myroot.node1.subnode1 = "holder";
myroot.node1.subnode2 = "holder";
myroot.node2 = new jsonObject();
myroot.node2.subnode2 = "holder";
myroot.node2.subnode3 = "holder";
myroot.node3 = new jsonObject();
myroot.node3.subnode = new array();
"arraystart"
myroot.node3.subnode.[aindex] = new jsonObject();
myroot.node3.subnode.[aindex] = "holder";
"endarray"
但我认为你应该细化目标。
+1给出了理想的结果(剔除了"),因为它造成了不明原因的问题,并且不需要100% – 2010-07-13 17:32:52
不知道这是做的最有效的方式,但希望这应该给你一些指点,如果确实没有做的工作完全:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="*[count(*)!=0]">
<xsl:param name="prefix" />
<xsl:value-of select="substring(concat($prefix,'.',name()),2)" />
<xsl:text> = new jsonObject(); </xsl:text>
<xsl:apply-templates select="*">
<xsl:with-param name="prefix" select="concat($prefix,'.',name())" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*[count(*)=0]">
<xsl:param name="prefix" />
<xsl:choose>
<xsl:when test="count(../*[name()=name(current())]) != 1">
<xsl:if test="position()=1">
<xsl:value-of select="substring(concat($prefix,'.',name()),2)" />
<xsl:text> = new array(); </xsl:text>
<xsl:text>"arraystart" </xsl:text>
<xsl:value-of select="substring(concat($prefix,'.',name()),2)" />
<xsl:text>[aindex] = new jsonObject(); </xsl:text>
<xsl:value-of select="substring(concat($prefix,'.',name()),2)" />
<xsl:text>[aindex] = "holder"; </xsl:text>
<xsl:text>"endarray" </xsl:text>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring(concat($prefix,'.',name()),2)" />
<xsl:text> = "holder"; </xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
我本来第二模板匹配*[text()]
,但不幸的是你的<subnode></subnode>
相当于<subnode />
,其中有没有任何文字,而不是0长度的文本。这意味着它假设任何没有孩子的节点应该被视为文本。
第二个模板中的'when'测试有点复杂,但它基本上检查当前节点是否是具有该名称的多个节点之一,并且如果它是第一个这样的节点,它会输出数组内容,否则什么都不做。这里最大的缺点是这样的数组只能是文本节点;例如,如果您的示例xml具有node1
而不是node2
,因此您在myroot
下有两个node1
元素,则不会看到任何“arraystart”内容。如果发生这种情况,它需要一些重新设计,但希望有足够的有用的例子来帮助。
编辑:忘记两个小点:
我使用
为换行符;如果需要,用
代替。
此外,substring(something,2)
位是因为它每追溯到一个级别后会追加一个节点名称,这意味着它每次都会有一个右边的开头。 substring(something,2)
只需要从第二个字符开始,换句话说,就是斩断那段时间。
+1给出了预期的结果 – 2010-07-13 17:33:33
有一件事让我深深的关注你的XML:你不知道根之外的特定节点名称。这是非常糟糕的XML设计,尽管从它的声音来看,这不是您的选择。如果您可以更改/说服某人将其更改为而不是(例如),它会使事情变得更容易。主要原因是您无法可靠地为这些节点创建模板;它将不得不成为一个全面的模板,而不是专门寻找'节点'元素。 –
Flynn1179
2010-07-12 21:41:35
实际上,真正的XML更大,没有数字。其中有些是已知的,但为此目的,我需要一个通用的解决方案,它是一个更大的应用程序的一部分,因此这种方法非常适合于手头的目的。 – 2010-07-13 17:37:34
注意自我:使用http://www.w3schools.com/xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog进行测试时,硬性限制为5023个字符的XML,如果失败,则不会有任何警告(空输出)。 – 2010-07-13 17:39:03