问题来了。 XMLDOM(Microsoft.XMLDOM 对象)不缩进 XML。它是人类无法读取的。 以前,在制作 XML 文档后,我只会运行此转换
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method='xml' version='1.0' encoding='UTF-8' indent='yes'/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在某处找到的。 然后我将使用原始 XML 对象 oXDoc,使用此 XSLT 转换创建此 XML 对象 oXsl 指令,然后调用transformNodeToObject,并创建一个第三个对象oRes,它将是一个已经缩进的XML,然后将该第三个对象保存到磁盘或其他地方。
oXDoc.transformNodeToObject(oXsl, oRes)
oRes.Save(cXmlFile)
它工作得很好,直到出现具有非默认名称空间的文档。 例如,像这样的 XML
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2">
<cbc:IssueDate>2024-11-07</cbc:IssueDate>
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="1234">AB90000012345</cbc:EndpointID>
</cac:Party></cac:AccountingSupplierParty></Invoice>
不再有效,但我在 XSL 中包含了所有名称空间,当我寻找答案时,所有名称似乎都在说同样的事情。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<xsl:output method='xml' version='1.0' encoding='UTF-8' indent='yes'/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
如果我删除原始 XML 文档中的所有前缀,它会起作用,它会缩进并包含所有名称空间绑定,但它没有用!我需要提供所有前缀,因为它们之间有很多通用名称,例如名称或 ID 等,否则它们会变得不明确。 那么正确的做法是什么呢?如何使其缩进文档并保留所有前缀而不出错?我按原样复制文档,仅添加缩进。无需实际转换。
我试过这个:
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<xsl:template match="@*|*:node()">
<xsl:copy>
<xsl:apply-templates select="@*|*:node()"/>
</xsl:copy>
和 这个
<xsl:template match="@*|:node()">
<xsl:copy>
<xsl:apply-templates select="@*|:node()"/>
</xsl:copy>
甚至这个
<xsl:template match="@*|:node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()|cbc:node()|cac:node()"/>
</xsl:copy>
还有很多很多其他的。
原始代码会出现错误,仅显示“msxml3:只有默认命名空间可以有空 URI”之类的内容。这真的很奇怪。所有命名空间都写在两个文档中,那么是什么给出了??? 其他尝试只是不喜欢该模式,并且错误显示“无效匹配模式”、“找到:”、“预期 eof”等等。
我也尝试过包括
extension-element-prefixes="cbc cac #default"
进入 xsl:stylesheet 元素,结果为零。
更新:
好吧,如果我在转换之前将 xml 保存到磁盘,然后再次将其加载到同一个对象中并进行转换,那么这最终可以工作。 也许元素的创建方式有问题?我只是将前缀和名称放在一起,如下所示:
oEl = oMainEl.appendChild(oXDoc.createElement("cac:Party")).appendChild(oXDoc.createElement("cbc:EndpointID"))
oEl.Text = "AB90000012345"
oEl.setAttribute("schemeID", "1234")
很奇怪。也许需要进行一些奇怪的操作
如果我没记错的话,使用 MSXML,要在某个命名空间中正确创建一般元素或节点,不要使用
createElement
,使用专有的 createNode
https://learn.microsoft.com/en -us/previous-versions/windows/desktop/ms757901(v=vs.85) 确保传入节点类型、限定名称和要创建的节点的命名空间 URI。
使用该方法创建元素与使用createNode是一样的 其中类型参数值为 NODE_ELEMENT 并且没有命名空间 指定。
您不能使用以下方法创建命名空间限定的元素 创建元素方法。无论命名空间前缀是否为 包含在 tagName 参数*,* 的 namespaceURI 属性中 新元素节点设置为空字符串“”。一个元素节点 作为 XML 文档加载操作的一部分构造的永远不会有 前缀和空命名空间统一资源标识符 (统一资源定位符)。您只能使用以下命令创建命名空间限定的元素 DOMDocument 对象的 createNode 方法。