Создание общего документа XSLT для преобразования любого элемента без полномочий root с дочерними элементами - PullRequest
0 голосов
/ 31 октября 2019

Следующий вопрос нацелен на образец XML-файла, который выглядит следующим образом:

<root>
   <Name>Name1</Name>
   <Description>Description1</Description>
   <Application>
      <ApplicationItem>1</ApplicationItem>
      <ApplicationItem>2</ApplicationItem>
      <ApplicationItem>3</ApplicationItem>
   </Application>
   <Location>
      <LocationItem>1</LocationItem>
      <LocationItem>2</LocationItem>
   </Location>
</root>

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

  <!-- Copy over entire XML document -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- Find Application and apply ApplicationItem template to it-->
  <xsl:template match="Application">
    <Application>
      <xsl:apply-templates select="ApplicationItem" />
    </Application>
  </xsl:template>

  <!-- Transform and remove ApplicationItem -->
  <xsl:template match="ApplicationItem">
    <xsl:value-of select=
    "concat(., substring('|', 1 div not(position()=last())))"/>
  </xsl:template>

  <!-- Find Location and apply LocationItem template to it-->
  <xsl:template match="Location">
    <Location>
      <xsl:apply-templates select="LocationItem" />
    </Location>
  </xsl:template>

  <!-- Transform and remove LocationItem -->
  <xsl:template match="LocationItem">
    <xsl:value-of select=
    "concat(., substring('|', 1 div not(position()=last())))"/>
  </xsl:template>

Однако я хотел бы иметь возможность создать общий xslt без необходимости конкретно указывать какой-либо из элементов, но применить вышеупомянутое преобразование к любому некорневому элементу с дочерними элементами. Пример псевдокода ниже

  <!-- Copy over entire XML document -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

<!-- Find non-root parent and apply child template to it-->
  <xsl:template match="*parent with children*">
    <*ParentElementName*>
      <xsl:apply-templates select="*ChildElementName OR ParentElementName+Item*" />
    </*ParentElementName*>
  </xsl:template>

  <!-- Transform and remove *ChildElementName* -->
  <xsl:template match="*ChildElementName*">
    <xsl:value-of select=
    "concat(., substring('|', 1 div not(position()=last())))"/>
  </xsl:template>

Могу ли я применить универсальный шаблон, который будет применяться к любому элементу, который соответствует вышеуказанным критериям? В моем реальном XML-файле есть десятки приведенных выше примеров XML, и этот канал может получить дополнительные экземпляры в будущем,Я хотел бы, чтобы xslt преобразовал их всех.

возможно?

1 Ответ

1 голос
/ 31 октября 2019

Да, это возможно. Чтобы реализовать это, используйте шаблон идентификации в сочетании со следующим шаблоном:

<xsl:template match="*[local-name() = concat(local-name(..),'Item')]">
    <xsl:value-of select="." />
    <xsl:if test="count(following-sibling::*[local-name() = local-name(current())]) > 0">|</xsl:if>    
</xsl:template>

Чтобы избавиться от ложных пробелов, вы также можете добавить шаблон

<xsl:template match="text()[not(normalize-space(.))]" />

или добавьте этот элемент на корневом уровне

<xsl:strip-space elements="*" />

Тогда результат теста будет:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <Name>Name1</Name>
  <Description>Description1</Description>
  <Application>1|2|3</Application>
  <Location>1|2</Location>
</root>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...