Преобразование XML с помощью XSLT - PullRequest
2 голосов
/ 08 августа 2011

У меня есть следующий пример XML:

<finding>
    <title>Found something</title>
    <heading>Severity:</heading>
    <text>Really low.</text>
    <heading>URL:</heading>
    <text>https://www.something.com:443</text>
    <heading>Description:</heading>
    <text>We have found an issue</text>
    <heading>Impact:</heading>
    <text>This is bad.</text>
    <heading>Recommendations:</heading>
    <text>Fix it!.</text>
</finding>

Легко ли это сделать с помощью XSLT?Я использую Python с lxml, если это помогает.Я хотел бы иметь XSLT, который даст мне следующее:

<finding>
    <title>Found something</title>
    <severity>Really low.</severity>
    <url>https://www.something.com:443</url>
    <description>We have found an issue</description>
    <impact>This is bad.</impact>
    <recommendations>Fix it!</recommendations>
</finding>

Спасибо!

Ответы [ 4 ]

0 голосов
/ 09 августа 2011

Это преобразование XSLT 1.0 правильно обрабатывает даже документы, в которых <heading> содержит произвольные не алфавитно-цифровые символы :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vUpper" select=
  "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

 <xsl:variable name="vLower" select=
  "'abcdefghijklmnopqrstuvwxyz'"/>

 <xsl:variable name="vDigits" select=
  "'0123456789'"/>

 <xsl:variable name="vAlhpaNum" select=
  "concat($vUpper, $vLower, $vDigits)"/>

 <xsl:template match=
  "node()[not(self::heading or self::text)]|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="heading">
  <xsl:element name=
  "{translate(translate(.,translate(.,$vAlhpaNum,''),''),
              $vUpper,
              $vLower
             )
   }">
   <xsl:value-of select="following-sibling::text[1]"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="text"/>
</xsl:stylesheet>

При применении к следующему документу XML (на основе предоставленного, но сделанного более сложным):

<finding>
    <title>Found something</title>
    <heading>Severity...</heading>
    <text>Really low.</text>
    <heading>URL?</heading>
    <text>https://www.something.com:443</text>
    <heading>Description:</heading>
    <text>We have found an issue</text>
    <heading>Impact!:</heading>
    <text>This is bad.</text>
    <heading>Recommendations!!!</heading>
    <text>Fix it!.</text>
</finding>

желаемый, правильный результат получен :

<finding>
   <title>Found something</title>
   <severity>Really low.</severity>
   <url>https://www.something.com:443</url>
   <description>We have found an issue</description>
   <impact>This is bad.</impact>
   <recommendations>Fix it!.</recommendations>
</finding>
0 голосов
/ 09 августа 2011

Вы можете использовать три шаблона:

Во-первых, шаблон преобразования для копирования всех узлов как есть

Затем два правила переопределяют обязательные элементы следующим образом:

 <xsl:template match="finding/heading">
  <xsl:element name="{lower-case(substring-before(.,':'))}">
    <xsl:value-of select="following-sibling::text[1]"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="finding/*[not(self::heading or self::title)]"/> 

, где lower-case() - это функция XPath 2.0. Для XPath 1.0 в нижнем регистре вы можете увидеть ответы на этот вопрос .

0 голосов
/ 09 августа 2011

С XSLT 2.0:

<!-- Identity Template / Copy by default -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="heading">
    <xsl:element name="{lower-case(replace(., ':', ''))}">
        <xsl:value-of select="following-sibling::text[1]"/>
    </xsl:element>
</xsl:template>

<xsl:template match="text"/>

Дайте вам точный вывод.

0 голосов
/ 09 августа 2011

XSLT был бы довольно приличным способом сделать это. Селектор для узлов text немного сложен, но шаблон из следующих строк должен это сделать (просто добавьте измененные версии этого для других заголовков).

<xsl:template match="text[preceding-sibling::heading[1][text()='Description:']]">
    <description><xsl:value-of select="." /></description>
</xsl:template>

Обратите внимание, что таблица стилей идентификации , вероятно, является разумной отправной точкой для добавления ваших шаблонов в.

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