如何使用命名空间前缀进行转换?添加它 do xslt 不起作用

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

问题来了。 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")

很奇怪。也许需要进行一些奇怪的操作

xml xslt xml-namespaces msxml xmldom
1个回答
0
投票

如果我没记错的话,使用 MSXML,要在某个命名空间中正确创建一般元素或节点,不要使用

createElement
,使用专有的
createNode
https://learn.microsoft.com/en -us/previous-versions/windows/desktop/ms757901(v=vs.85) 确保传入节点类型、限定名称要创建的节点的命名空间 URI。

参见https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms757047(v=vs.85)中关于createElement的备注:

使用该方法创建元素与使用createNode是一样的 其中类型参数值为 NODE_ELEMENT 并且没有命名空间 指定。

您不能使用以下方法创建命名空间限定的元素 创建元素方法。无论命名空间前缀是否为 包含在 tagName 参数*,* 的 namespaceURI 属性中 新元素节点设置为空字符串“”。一个元素节点 作为 XML 文档加载操作的一部分构造的永远不会有 前缀和空命名空间统一资源标识符 (统一资源定位符)。您只能使用以下命令创建命名空间限定的元素 DOMDocument 对象的 createNode 方法。

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