XSLT 1.0 Все узлы между двумя разными узлами - PullRequest
0 голосов
/ 06 ноября 2018

У меня есть список узлов в XML, которые мне нужно превратить в некие структурированные данные, и у меня возникли некоторые проблемы.

У меня есть хорошее представление о том, как получить дочерние данные под заголовками (Клиент, Пользователь), но я действительно борюсь с тем, как выбирать между двумя узлами с разными именами, включая эти узлы. Я действительно ищу XPath, который позволит выбрать эти области.

Так что для узла Customer мне нужно выбрать между CustomerName через узел перед UserName (в реальных данных гораздо больше узлов). Затем для каждого пользователя (которого есть неизвестное количество) мне нужно пройти между UserName и узлом перед следующим UserName, опять же с гораздо более чем двумя узлами в реальных данных.

Я пытался использовать комбинацию «предыдущий брат, следующий брат и счет», но я просто не могу заставить работать правильную комбинацию. Любые указатели в правильном направлении будут большой помощью.

Я бы предпочел XSLT 1.0, но для меня доступно 2.0.

Пример данных:

<Data>
  <CustomerName>
    <Name>ABCCompany</Name>
  </CustomerName>
  <CustomerAddress>
    <City>AnyCity</City>
    <State>AnyState</State>
  </CustomerAddress>
  <UserName>
    <Name>Betty<Name>
  </UserName>
  <UserAddress>
    <City>AnyCity</City>
    <State>AnyState</State>
  </UserAddress>
  <UserName>
    <Name>Johnny</Name>
  </UserName>
  <UserAddress>
    <City>AnyCity</City>
    <State>AnyState</State>
  </UserAddress>
</Data>

Желаемый вывод:

<Data>
  <Customer>
    <CustomerName>
      <Name>ABCCompany</Name>
    </CustomerName>
    <CustomerAddress>
    <City>AnyCity</City>
    <State>AnyState</State>
    </CustomerAddress>
  </Customer>
  <Users>
    <User>
      <UserName>
        <Name>Betty</Name>
      </UserName>
      <UserAddress>
    <City>AnyCity</City>
    <State>AnyState</State>
      </UserAddress>
    </User>
    <User>
      <UserName>
        <Name>Johnny</Name>
      </UserName>
      <UserAddress>
    <City>AnyCity</City>
    <State>AnyState</State>
      </UserAddress>
    </User>
  </Users>
</Data>

1 Ответ

0 голосов
/ 07 ноября 2018

Вот примерный пример того, как вы могли бы подойти к этому в XSLT 2.0 :

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/Data">
    <xsl:copy>
        <xsl:for-each-group select="*" group-starting-with="CustomerName|UserName">
            <group type="{name(current-group()[1])}">
                <xsl:copy-of select="current-group()" />
            </group>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Применительно к вашему примеру ввода (с поправкой на корректность!) Результат будет:

<?xml version="1.0" encoding="UTF-8"?>
<Data>
   <group type="CustomerName">
      <CustomerName>
         <Name>ABCCompany</Name>
      </CustomerName>
      <CustomerAddress>
         <City>AnyCity</City>
         <State>AnyState</State>
      </CustomerAddress>
   </group>
   <group type="UserName">
      <UserName>
         <Name>Betty</Name>
      </UserName>
      <UserAddress>
         <City>AnyCity</City>
         <State>AnyState</State>
      </UserAddress>
   </group>
   <group type="UserName">
      <UserName>
         <Name>Johnny</Name>
      </UserName>
      <UserAddress>
         <City>AnyCity</City>
         <State>AnyState</State>
      </UserAddress>
   </group>
</Data>

Вы можете использовать выражение name(current-group()[1]), чтобы выбрать подходящий элемент-оболочку для каждой группы.


Демо: http://xsltransform.hikmatu.com/bdxtpC

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