Powershell $xslt.Transform() 以及在 xslt 中使用 Document() 函数的问题

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

我制作了一个 xslt 脚本,将 XML Peppol/UBL 发票转换为可以导入到我们的 ERP 系统中的 xml 格式。该脚本使用以下命令在 Powershell 中完美运行:

$xsl=’ C:\temp\Axtension_UBL_TEST2.xslt’
$xslt.Load($xsl)
$xslt.Transform($_, $output)

直到我决定使用 Document() 函数将部分脚本与脚本外部的供应商参数一起引入。然后我收到以下错误:

使用“2”个参数调用“Transform”时出现异常:“禁止执行‘document()’函数。使用 XsltSettings.EnableDocumentFunction 属性启用它。

然后我将 powershell 转换脚本更改为:

$XsltSettings = New-Object System.Xml.Xsl.XsltSettings   
$XsltSettings.EnableDocumentFunction = 1   
$XmlUrlResolver = New-Object System.Xml.XmlUrlResolver   
$xslt = New-Object System.Xml.Xsl.XslCompiledTransform;   
$xslt.Load($xsl, $XsltSettings,$XmlUrlResolver)   
$xslt.Transform($_, $output)   

我现在收到以下错误,现在我陷入困境。有人可以帮我吗?

$xslt.Transform($_, $output) 使用“2”个参数调用“Transform”时出现异常:“加载文档“Vendors.xml”时发生错误。有关错误的完整描述,请参阅 InnerException。”

Vendors.xml 指的是 xslt 脚本中的文件名,用于将文件加载到 xslt 中。 Axtension_UBL_TEST2.xslt’ 和 Vendors.xml 都位于同一文件夹中,并且拼写(大写)正确。

我也不知道如何使用 InnerException 使完整的错误可见。

这是 xslt 脚本的工作部分,它在 Powershell 中生成相同的错误:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:ccts="urn:un:unece:uncefact:documentation:2" xmlns:qdt="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2" xmlns:udt="urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2" xmlns:default="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" exclude-result-prefixes="cac cbc ccts qdt udt default">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
    <xsl:template match="/">
        <PurchaseInvoices_version_1.0>
            <xsl:for-each select="default:Invoice">
                <PurchaseInvoice>
                    <xsl:variable name="current-vendor-name" select="cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc:Name"/>
                    <xsl:variable name="vendor-data" select="document('Vendors3.xml')/vendors/vendor[name=$current-vendor-name and administration='XYZ']"/>
                    <xsl:variable name="VendorShortName" select="$vendor-data/shortName"/>
                    <xsl:value-of select="$vendor-data"/> 
                </PurchaseInvoice>
            </xsl:for-each>
        </PurchaseInvoices_version_1.0>
    </xsl:template>
</xsl:stylesheet>

Vendors3.xml 文件包含以下内容:

<vendors>
    <vendor>
        <administration>XYZ</administration>
        <name>TestVendor</name>
        <shortName>Tvendor</shortName>
        <accountNumber>20250</accountNumber>
        <invoiceType/>
        <IncludeOrderReference>No</IncludeOrderReference>
        <lineText>ItemName</lineText>
        <lines>Yes</lines>
    </vendor>
</vendors>

用于输入的xml是:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Invoice xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:ccts="urn:un:unece:uncefact:documentation:2" xmlns:qdt="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2" xmlns:udt="urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2" xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
  <cbc:UBLVersionID>2.1</cbc:UBLVersionID>
  <cbc:CustomizationID>urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol4a:ver2.0</cbc:CustomizationID>
  <cbc:ProfileID>urn:www.cenbii.eu:profile:bii04:ver2.0</cbc:ProfileID>
  <cac:AccountingSupplierParty>
    <cac:Party>
      <cac:PartyName>
        <cbc:Name>TestVendor</cbc:Name>
      </cac:PartyName>
    </cac:Party>
  </cac:AccountingSupplierParty>
</Invoice>

使用像 Oxygen 这样的 xslt 编辑器时的输出给出以下输出“

<?xml version="1.0" encoding="utf-8"?>
<PurchaseInvoices_version_1.0>
   <PurchaseInvoice>
        XYZ
        TestVendor
        Tvendor
        20250
        
        No
        ItemName
        Yes
    </PurchaseInvoice>
</PurchaseInvoices_version_1.0

我使用 TransformXML 脚本(使用 $Xslt_Settings.EnableDocumentFunction = 1 )来执行此操作,这似乎提供了有关错误的更多信息:禁止解析外部 URI

InnerException 打印如下:

SourceUri      : 
LineNumber     : 0
LinePosition   : 0
Message        : An error occurred while loading document 'Vendors.xml'. See InnerException for a complete description of the error.
TargetSite     : System.Xml.XPath.XPathNavigator GetDataSource(System.String, System.String)
Data           : {}
InnerException : System.Xml.XmlException: Resolving of external URIs was prohibited.
                    at System.Xml.XmlNullResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn)
                    at System.Xml.Xsl.Runtime.XmlQueryContext.GetDataSource(String uriRelative, String uriBase)
HelpLink       : 
Source         : System.Private.Xml
HResult        : -2146231998
StackTrace     :    at System.Xml.Xsl.Runtime.XmlQueryContext.GetDataSource(String uriRelative, String uriBase)
                    at <xsl:template match="/">(XmlQueryRuntime , XPathNavigator )
                    at Root(XmlQueryRuntime )
                    at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer)
                    at System.Xml.Xsl.XslCompiledTransform.Transform(String inputUri, String resultsFile)
                    at CallSite.Target(Closure , CallSite , Object , Object , Object )
xml powershell xslt
1个回答
0
投票

使用

XslCompiledTransform
及其
Transform/4
方法。我在使用 PowerShell 7.4 时遇到了同样的问题,以下方法对我有用。

$XmlUrlResolver = New-Object System.Xml.XmlUrlResolver
$XsltSettings = New-Object System.Xml.Xsl.XsltSettings($true, $true)
$XsltParams = New-Object System.Xml.Xsl.XsltArgumentList
$XslInputElement = New-Object System.Xml.Xsl.XslCompiledTransform

$XSLWriterSettings = New-Object System.Xml.XmlWriterSettings
$XSLWriterSettings.Indent = $True
$XSLWriterSettings.IndentChars = "    "
$XSLWriterSettings.NewLineChars ="`r`n"
$XSLWriterSettings.Encoding = New-Object System.Text.UTF8Encoding  $False
$XSLWriter = [System.Xml.XmlWriter]::Create("output.xml", $XSLWriterSettings)

$InFile = New-Object System.Xml.XPath.XPathDocument("input.xml")

$XslInputElement.Load("transform.xslt", $XsltSettings, $XmlUrlResolver)
$XslInputElement.Transform($InFile, $XsltParams, $XSLWriter, $XmlUrlResolver)

使用

XsltSettings($true, $true)
也很重要,因为它可以使用
document
功能。

当然,具体的编写器设置与此无关,但关键是能够使用接受 URL 解析器的

Transform
版本。此外,使用
XslTransform
似乎会悄无声息地失败,并在转换中产生一个空数据集。

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