使用 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 - 我希望执行以下操作:
-
删除所有命名空间信息架构等,但保留打开和关闭标记(部分完成)
<rs:data>
需要变成 <data>
没有任何属性(如何从数据中的 xmlns 中删除该属性?)
<rs:insert>
需要消失(完成)
<z:row>
需要变成 <row>
(完成)
输入数据可能不同,但结构相同 - 这就是我需要像以前一样的通用规则集的原因。
【问题讨论】:
不要假装在 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 信息,例如以上是关于使用 XSL 样式表进行 ADO XML 清理的主要内容,如果未能解决你的问题,请参考以下文章
为啥 XSL 样式表显示没有 XML(信息/值)的 html 表