Имена элементов XSLT в виде строки - PullRequest
0 голосов
/ 13 июля 2010

Я хочу вывести что-то похожее на следующее, используя 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 глубин)
  • Я НЕ знаю чисел, позиций или элементов массива, но дочерние узлы (элементы)одно и то же имя для этих групп.
  • Несколько массивов могут существовать или могут существовать на любой глубине дерева.
  • Элементы с текстом не имеют дочерних узлов

Ответы [ 2 ]

1 голос
/ 13 июля 2010

Эта таблица стилей:

<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"

Но я думаю, вы должны уточнить свою цель.

0 голосов
/ 13 июля 2010

Не уверен, что это самый эффективный способ сделать это, но, надеюсь, это даст вам несколько советов, если на самом деле он не выполняет свою работу полностью:

<?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.Это означает, что предполагается, что любой узел, у которого нет дочерних элементов, должен обрабатываться так, как если бы он был текстовым.

Тест «когда» во втором шаблоне немного запутан, но в основном он проверяет, является ли текущий узелодин из нескольких с таким именем, и если это первый такой узел, он выводит массив данных, в противном случае ничего не делает.Большой недостаток в том, что такие массивы могут быть только текстовыми узлами;например, если в вашем образце xml вместо node2 было node1, так что у вас было два элемента node1 в myroot, вы не увидели бы ничего из "arraystart".Если это может произойти, понадобится немного изменить дизайн, но, надеюсь, здесь достаточно полезных примеров, чтобы помочь.

Редактировать: Забыл два небольших пункта:

Я использую &#10; для символа новой строки;замените его на &#13;&#10;, если требуется.

Кроме того, биты substring(something,2) связаны с тем, что он добавляет точку, за которой следует имя узла, каждый раз, когда он понижается до уровня, что означает, что он имеет правоначало каждый раз.substring(something,2) просто берет все, начиная со 2-го символа, другими словами, обрезая этот период.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...