使用 XSLT 转换 XML

发布于 2024-11-28 10:03:46 字数 1064 浏览 0 评论 0原文

我有以下 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>

谢谢!

I have the following XML sample:

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

Is this easily done with an XSLT? I am using Python with lxml if that helps.
What I would like to have is an XSLT that will give me the following:

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

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

泪是无色的血 2024-12-05 10:03:46

XSLT 将是一种相当不错的方法。 text 节点的选择器有点复杂,但是遵循以下几行的模板应该可以做到这一点(只需为其他标题添加此内容的修改版本)。

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

请注意,身份样式表可能是添加模板的合理起点。

XSLT would be a fairly decent way to do it. The selector for the text nodes is a little complex, but a template along the following lines should do it (just add modified versions of this for your other headings).

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

Note that the identity stylesheet is probably a reasonable starting point for adding your templates to.

初心未许 2024-12-05 10:03:46

使用 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"/>

给你准确的输出。

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

Give you the exact output.

虚拟世界 2024-12-05 10:03:46

您可以使用三个模板:

首先,身份转换 按原样复制所有节点的模板 然后

,覆盖所需元素的两个规则如下:

 <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 小写字母处理,您可以在此 问题

You can use three templates:

First, the identity transformation template to copy all nodes as is

Then, two rules overriding the required elements as follows:

 <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)]"/> 

where lower-case() is XPath 2.0 function. For XPath 1.0 lower-case handling you can see the answers in this question.

泪眸﹌ 2024-12-05 10:03:46

此 XSLT 1.0 转换甚至可以正确处理 包含任意非字母数字字符的文档

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

This XSLT 1.0 transformation correctly processes even documents in which <heading> contains arbitrary non-alphanumeric characters:

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

When applied on the following XML document (based on the provided one, but made more challenging):

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

the wanted, correct result is produced:

<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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文