代码之家  ›  专栏  ›  技术社区  ›  Mark Schultheiss

XSLT元素名称作为字符串

  •  -2
  • Mark Schultheiss  · 技术社区  · 15 年前

    我想使用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"
    

    • =“持有人”;可以是任何独特的,因为我会改变这个稍后
    • 任何独特的东西我都会改变 后来
    • 超越根。
    • (约6-7深)
    • 我不知道号码和位置 或数组元素,但子元素
    • 可能/确实存在多个数组,并且可以
    • 包含文本的元素没有子元素 节点
    2 回复  |  直到 15 年前
        1
  •  1
  •   user357812 user357812    15 年前

    <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();&#xA;')"/>
            <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(),
                                         ' = &quot;holder&quot;;&#xA;')"/>
        </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();&#xA;',
                                         '&quot;arraystart&quot;&#xA;')"/>
            <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();&#xA;</xsl:when>
                <xsl:otherwise>"holder";&#xA;</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"
    

    但我认为你应该完善你的目标。

        2
  •  0
  •   Flynn1179    15 年前

    <?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();&#10;</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();&#10;</xsl:text>
              <xsl:text>"arraystart"&#10;</xsl:text>
              <xsl:value-of select="substring(concat($prefix,'.',name()),2)" />
              <xsl:text>[aindex] = new jsonObject();&#10;</xsl:text>
              <xsl:value-of select="substring(concat($prefix,'.',name()),2)" />
              <xsl:text>[aindex] = "holder";&#10;</xsl:text>
              <xsl:text>"endarray"&#10;</xsl:text>
            </xsl:if>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="substring(concat($prefix,'.',name()),2)" />
            <xsl:text> = "holder";&#10;</xsl:text>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
    </xsl:stylesheet>
    

    我最初有第二个模板匹配 *[text()] <subnode></subnode> 相当于 <subnode /> ,它完全没有文本,而不是长度为0的文本。这意味着它假设任何没有子节点的节点都应该被视为文本。

    第二个模板中的'when'测试有点复杂,但它基本上检查当前节点是否是具有该名称的多个节点中的一个,如果是第一个这样的节点,则输出数组内容,否则什么也不做。这里最大的缺点是这样的数组只能是文本节点;例如,如果您的示例xml node1 node2 以至于你有两个 节点1 myroot ,你不会看到任何“arraystart”的东西。如果可以的话,它将需要重新设计一点,但希望这里有足够的有用的例子来帮助。

    &#10; 换行符;将此替换为 &#13;&#10; 如果需要。

    此外,还有 substring(something,2) 位是因为它每次下降一个级别时都会附加一个句点,后跟节点名,这意味着它每次都会在开头加一个句点。 子串(something,2) 只需要从第二个字符开始,换言之,去掉那个句号。