使用parse-xml将文本转换为XML中的节点

问题描述 投票:0回答:1

我正在使用 Access 数据库的 XML 输出,其中某些节点内的文本需要通过 XSLT 转换为节点本身,然后通过 Adobe FrameMaker 运行以创建出版物。在网上,我看到了许多对 XSLT 函数的引用,我应该可以使用它,称为 parse-xml(Framemaker 的 XSLT 可以使用 Saxon 9.8),这应该允许我做我想做的事情。我还没有找到使用此函数的任何示例,而且我对 XSLT 还很陌生,无法完全想象代码的正确构造。此外,如果您知道基于 Web 的 XSLT 3.0 测试器,那将会有很大帮助。我一直在使用 XSLtransform.net,这非常棒,但它不支持 XSLT 3.0(至少像 Framemaker 一样通过 Saxon 9.8)。

我需要转换的 XML:

<?xml version="1.0" encoding="UTF-8"?>
<dataroot xmlns:od="urn:schemas-microsoft-com:officedata" generated="2023-09-26T10:37:15">
<TEQuery>
<IntID>PR090F</IntID>
<TEName>Exempt Lease From Taxable Owner</TEName>
<Description>

&lt;div&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;&amp;nbsp;Leased properties that qualify for this exemption are reported under one of the following expenditures: &lt;/font&gt;&lt;/div&gt;

&lt;ul&gt;
 &lt;ul&gt;
  &lt;ul&gt;
   &lt;ul&gt;
    &lt;ul&gt;
     &lt;ul&gt;
      &lt;ul&gt;
       &lt;li&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;PR001F, &lt;/font&gt;&lt;/li&gt;
       &lt;li&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;PR007F,&lt;/font&gt;&lt;/li&gt;
       &lt;li&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;PR079F, &lt;/font&gt;&lt;/li&gt;
       &lt;li&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;PR083F, &lt;/font&gt;&lt;/li&gt;
       &lt;li&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;PR085F, &lt;/font&gt;&lt;/li&gt;
       &lt;li&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;PR086F, &lt;/font&gt;&lt;/li&gt;
      &lt;/ul&gt;
     &lt;/ul&gt;
    &lt;/ul&gt;
   &lt;/ul&gt;
  &lt;/ul&gt;
 &lt;/ul&gt;
&lt;/ul&gt;
</Description>
<TaxSort>2</TaxSort>
</TEQuery>
</dataroot>

我想要的输出如下:

<dataroot xmlns:od="urn:schemas-microsoft-com:officedata"
          generated="2023-09-26T10:37:15">
  
   <TaxExpenditure id="PR090F" TAXSORT="2">Exempt Lease From Taxable Owner
      <Description>
&lt;div&gt;&lt;font face="Times New Roman" color=black&gt;&amp;nbsp;Leased properties that qualify for this exemption are reported under one of the following expenditures: &lt;/font&gt;&lt;/div&gt;
<unorderedlist>
       <listitem>;&lt;font face="Times New Roman" color=black&gt;PR001F, &lt;/font&gt;</listitem>
       <listitem>;&lt;font face="Times New Roman" color=black&gt;PR007F, &lt;/font&gt;</listitem>
       <listitem>&lt;font face="Times New Roman" color=black&gt;PR079F, &lt;/font&gt;</listitem>
       <listitem>&lt;font face="Times New Roman" color=black&gt;PR083F, &lt;/font&gt;</listitem>
       <listitem>&lt;font face="Times New Roman" color=black&gt;PR085F, &lt;/font&gt;</listitem>
       <listitem>&lt;font face="Times New Roman" color=black&gt;PR086F, &lt;/font&gt;</listitem>
   </unorderedlist>
   </TaxExpenditure>
</dataroot>

这是我当前的 XSL 代码,除了将列表字符串转换为节点之外,它可以完成迄今为止的所有操作,但我对 parse-xml 函数的后续步骤 100% 迷失,无论它是否应该驻留在 xsl:template 语句中或其他东西等。通过 xslt 删除文本的“”部分所提供的任何帮助也将不胜感激,尽管我怀疑我可能需要稍后在 xslt 之外的过程中执行此操作或将它们也转换为在删除节点之前先到节点。

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

<xsl:template match="/ | @* | node()">
        <xsl:copy>
               <xsl:apply-templates select="@* | node()" />
         </xsl:copy>
 </xsl:template>

<xsl:template match="TEQuery">
    <TaxExpenditure>
      <xsl:attribute name="id" select="IntID"/>
      <xsl:attribute name="TAXSORT" select="TaxSort"/>
      <xsl:value-of select = "TEName"/>
      <xsl:apply-templates select="@* | node()" />
    </TaxExpenditure>
</xsl:template>

<xsl:template match="IntID"/>
<xsl:template match="TaxSort"/>
<xsl:template match="TEName"/>
</xsl:stylesheet>
xml xml-parsing xslt-3.0
1个回答
0
投票

正如我在评论中指出的那样,根据 XML 规则,

Description
元素的内容格式不正确,因为至少有一些属性值未由引号字符正确分隔。

因此

parse-xml
parse-xml-fragment
都无法成功解析该内容。

检查您的 Framemaker 中的 Saxon 版本是否是商业版本(即 PE 或 EE),然后您可以使用(取决于具体版本)扩展功能

saxon:parse-html
https://www.saxonica.com/ html/documentation10/functions/saxon/parse-html.html 或新的 XPath 4
fn:parse-html
.

另一方面,有一个用纯 XSLT 2 完成的漂亮的小型 HTML 标签汤解析器实现,即 David Carlisle 的 https://github.com/davidcarlisle/web-xslt/blob/main/htmlparse/htmlparse.xsl ,您可以导入然后使用(假设命名空间声明

xmlns:dc="data:,dpc"
),例如

<xsl:import href="https://raw.githubusercontent.com/davidcarlisle/web-xslt/main/htmlparse/htmlparse.xsl"/>

<xsl:template match="Description">
  <xsl:copy>
    <xsl:apply-templates select="dc:htmlparse(., '', true())"/>
  </xsl:copy>
</xsl:template>

然后您基本上将 HTML 作为 XDM 节点(例如

div
font
ul
li
元素节点),并且您可以添加模板来转换它们,例如

<xsl:template match="li">
  <listitem>
   <xsl:apply-templates/>
  </listitem>
</xsl:template>

尚不清楚您是否真的想要一些像

listitem
这样的结果元素,但随后又在内部转义了标记;当然,您可以使用
fn:serialize
序列化节点,尽管在解析它们之后并且使用序列化 XSLT 允许和 Saxon 实现(例如,可能在属性值周围使用引号),这意味着不可能保留原始转义标记。

至于在浏览器中摆弄 XSLT 3,有 https://martin-honnen.github.io/xslt3fiddle/ 使用 SaxonJS(当前为 2.5)(你的示例和我的 XSLT 建议),然后我有 Saxon https://xsltfiddle.liberty-development.net/ 中的 10 以及 https://xsltfiddle-beta.liberty-development.net/.

中的各种撒克逊版本

请记住,https://xsltfiddle.liberty-development.net/允许您将小提琴存储在数据库中,但随后您可以与网络共享它们,因此请确保您不使用私有输入数据保存任何内容或您想要保密的代码。

© www.soinside.com 2019 - 2024. All rights reserved.