使用 XSL 样式表进行 ADO XML 清理

Posted

技术标签:

【中文标题】使用 XSL 样式表进行 ADO XML 清理【英文标题】:ADO XML cleanup using XSL stylesheet 【发布时间】:2021-12-13 11:23:50 【问题描述】:

我不得不将用于“清理”ADO XML 的 XSL 样式表命名空间从 http://www.w3.org/TR/WD-xsl 升级到 http://www.w3.org/1999/XSL/Transform - 现在使用该样式表无法提供与以前相同的输出,因此会破坏功能。

我尝试了许多组合,但没有一个提供与以前相同的结果 - 我是 XSL 新手。你能帮忙吗?

我在 VB 中使用 MSXML2.DOMDocument60.transformNodeToObject 作为 API 来应用样式表。

这是我的输入 ADO XML:

<xml xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
xmlns:rs="urn:schemas-microsoft-com:rowset"
xmlns:z="#RowsetSchema">
  <s:Schema id="RowsetSchema">
    <s:ElementType name="row" content="eltOnly" rs:updatable="true">
      <s:AttributeType name="ShipperID" rs:number="1"
        rs:basetable="shippers" rs:basecolumn="ShipperID"
        rs:keycolumn="true">
        <s:datatype dt:type="int" dt:maxLength="4" rs:precision="10"
          rs:fixedlength="true" rs:maybenull="false"/>
      </s:AttributeType>
      <s:AttributeType name="CompanyName" rs:number="2"
        rs:nullable="true" rs:write="true" rs:basetable="shippers"
        rs:basecolumn="CompanyName">
        <s:datatype dt:type="string" dt:maxLength="40" />
      </s:AttributeType>
      <s:AttributeType name="Phone" rs:number="3" rs:nullable="true"
        rs:write="true" rs:basetable="shippers"
        rs:basecolumn="Phone">
        <s:datatype dt:type="string" dt:maxLength="24"/>
      </s:AttributeType>
      <s:extends type="rs:rowbase"/>
    </s:ElementType>
  </s:Schema>
  <rs:data>
    <rs:insert>
      <z:row ShipperID="1" CompanyName="Speedy Express" Phone="(503) 111-4567"/>
      <z:row ShipperID="2" CompanyName="United Package" Phone="(503) 222-4567"/>
      <z:row ShipperID="3" CompanyName="Federal Shipping" Phone="(503) 333-4567"/>
    </rs:insert>
  </rs:data>
</xml>

这是旧的样式表:

<?xml version='1.0'?>                                       
<stylesheet xmlns='http://www.w3.org/TR/WD-xsl'>
  <template>
    <copy>
      <apply-templates select="@* | * | comment() | pi() | text()"/>
    </copy>
  </template>
  <template match="rs:insert" >
    <apply-templates select="@* | * | comment() | pi() | text()"/>
  </template>
  <template match="rs:data" >
    <element name="data">
      <apply-templates select="@* | * | comment() | pi() | text()"/>
    </element>
  </template>
  <template match="z:row" >
    <element name="row">
      <apply-templates select="@* | * | comment() | pi() | text()"/>
    </element>
  </template>
  <template match="@rs:forcenull" >
    <attribute name="forcenull"/>
  </template>
  <template match="s:Schema" />
  <template match="@xmlns:s" />
  <template match="@xmlns:dt" />
  <template match="@xmlns:rs" />
  <template match="@xmlns:z" />
</stylesheet>

这是我之前得到的结果,也是我现在需要的结果:

<xml>
  <data>
      <row ShipperID="1" CompanyName="Speedy Express" Phone="(503) 111-4567"></row>
      <row ShipperID="2" CompanyName="United Package" Phone="(503) 222-4567"></row>
      <row ShipperID="3" CompanyName="Federal Shipping" Phone="(503) 333-4567"></row>
  </data>
</xml>

这是新的样式表(正在进行中):

<?xml version="1.0" encoding="UTF-8"?>
<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version = "3.0"
 xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">
  <template match="/">
    <copy>
      <apply-templates select="@* | * | comment() | processing-instruction() | text()" />
    </copy>
  </template>
  <template match="rs:insert">
      <apply-templates select="@* | * | comment() | processing-instruction() | text()"/>
  </template>
  <template match="rs:data">
    <element name="data">
      <apply-templates select="@* | * | comment() | processing-instruction() | text()"/>
    </element>
  </template>
  <template match="z:row">
    <element name="row">
      <copy-of select="@* | * | comment() | processing-instruction() | text()"/>
    </element>
  </template>
  <template match="@rs:forcenull" >
    <attribute name="forcenull"/>
  </template>
  <template match="s:Schema"/>
  <template match="@xmlns:s"/>
  <template match="@xmlns:dt"/>
  <template match="@xmlns:rs"/>
  <template match="@xmlns:z"/>
</stylesheet>

这是我现在得到的结果(错误,与以前不是 100% 相同):

<?xml version="1.0" encoding="UTF-16"?>
<data xmlns="http://www.w3.org/1999/XSL/Transform">
  <row ShipperID="1" CompanyName="Speedy Express" Phone="(503) 111-4567"></row>
  <row ShipperID="2" CompanyName="United Package" Phone="(503) 222-4567"></row>
  <row ShipperID="3" CompanyName="Federal Shipping" Phone="(503) 333-4567"></row>
</data>

基本上给定输入 ADO XML - 我希望执行以下操作:

    删除所有命名空间信息架构等,但保留打开和关闭标记(部分完成) &lt;rs:data&gt; 需要变成 &lt;data&gt; 没有任何属性(如何从数据中的 xmlns 中删除该属性?) &lt;rs:insert&gt; 需要消失(完成) &lt;z:row&gt; 需要变成 &lt;row&gt;(完成)

输入数据可能不同,但结构相同 - 这就是我需要像以前一样的通用规则集的原因。

【问题讨论】:

不要假装在 MSXML 中使用version="3.0",它是一个 XSLT 1 处理器。 【参考方案1】:

如果您需要删除命名空间,请使用

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

<xsl:template match="@*">
  <xsl:attribute name="local-name()">
    <xsl:value-of select="."/>
  </xsl:attribute>
</xsl:template>

作为基本模板。

然后

<xsl:template match="rs:insert">
  <xsl:apply-templates/>
</xsl:template>

对于名称更改,例如

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

确保你使用例如exclude-result-prefixes="z rs" 位于 xsl:stylesheet 元素上,用于您在 XSLT 中声明的任何命名空间,只是为了从输入中选择元素或属性,但您不希望命名空间出现在结果中。

并且不要将 XSLT 代码放入默认命名空间中,因此请使用例如

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version = "1.0"
 xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
 xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" exclude-result-prefixes="z s rs">

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


<xsl:template match="@*">
  <xsl:attribute name="local-name()">
    <xsl:value-of select="."/>
  </xsl:attribute>
</xsl:template>


<xsl:template match="rs:insert | xml">
  <xsl:apply-templates/>
</xsl:template>


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

<xsl:template match="s:Schema"/>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/jxWZS8g/1

【讨论】:

感谢您的帮助!不幸的是,这并不能解决整个问题——我的输出中仍然有模式和 xmlns 信息,例如w3.org/1999/XSL/Transform"><Schemaid="RowsetSchema"> 哪个更好但是我想摆脱 xmlns= 和 Schema id 位,所以我将拥有一个干净的 结构。 我把它放在这里以便更好地看到xsltfiddle.liberty-development.net/jxWZS8g 我的目标是只有这个: @cibuan,查看编辑,显然您需要更多匹配项来转换或跳过其他输入元素,但建议的方法与以前一样。

以上是关于使用 XSL 样式表进行 ADO XML 清理的主要内容,如果未能解决你的问题,请参考以下文章

预处理 XSL 样式表 - 包括外部文档

为啥 XSL 样式表显示没有 XML(信息/值)的 html 表

xml 错误 xsl 样式表

XSL 转换以输出许多嵌入式 XSL 样式表

xsl 在带有样式表的 Multiple 的 xml 文档上创建

我需要一个简单的命令行程序来使用 XSL 样式表转换 XML [关闭]