1

我使用 XML 数据绑定向导为 IRS XML 规范文件创建了一个类。我有两个问题我找不到答案(我已经花了几个小时尝试)。

这是我需要的 XML 输出的片段:

<?xml version="1.0" encoding="UTF-8"?>
<h1:ACAUIBusinessHeader xmlns="urn:us:gov:treasury:irs:ext:aca:air:7.0" xmlns:irs="urn:us:gov:treasury:irs:common" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:acabushdr="urn:us:gov:treasury:irs:msg:acabusinessheader" xmlns:h1="urn:us:gov:treasury:irs:msg:acauibusinessheader" xsi:schemaLocation="urn:us:gov:treasury:irs:msg:acauibusinessheader IRS-ACAUserInterfaceHeaderMessage.xsd">
    <acabushdr:ACABusinessHeader>
        <UniqueTransmissionId>00000000-0000-0000-0000-000000000000:SYS12:BB000::T</UniqueTransmissionId>
        <irs:Timestamp>2001-12-17T09:30:47Z</irs:Timestamp>
    </acabushdr:ACABusinessHeader>
    <ACATransmitterManifestReqDtl>
        <PaymentYr>1000</PaymentYr>
        <PriorYearDataInd>1</PriorYearDataInd>
        <irs:EIN>000000000</irs:EIN>
    </ACATransmitterManifestReqDtl>
</h1:ACATransmitterManifestReqDtl>

如您所见,根节点不使用默认的 xmlns 命名空间。如果我在 GetDocBinding() 调用中将“h1:”前缀添加到名称中,那么它会将“h1:”前缀添加到所有子节点,这不是我需要的。

此外,我手动编辑了数据绑定向导创建的类,以便我可以使用 DeclareNamespace() 方法定义额外的命名空间。然而,当我尝试使用 RegisterChildNode() 方法的可选第三个参数来定义 URI 时,当我尝试使用该节点的属性时它会崩溃。

这是已编辑类的代码片段:

    _di_IXMLTransmitterACAUIBusinessHeaderType __fastcall GetACAUIBusinessHeader(Xml::Xmlintf::_di_IXMLDocument Doc)
    {
        return (_di_IXMLTransmitterACAUIBusinessHeaderType) Doc->GetDocBinding("ACAUIBusinessHeader", __classid(TXMLTransmitterACAUIBusinessHeaderType), eACA_UI_Header_TargetNamespace);
    };

    _di_IXMLTransmitterACAUIBusinessHeaderType __fastcall GetACAUIBusinessHeader(Xml::Xmldoc::TXMLDocument *Doc)
    {
        Xml::Xmlintf::_di_IXMLDocument DocIntf;
        Doc->GetInterface(DocIntf);
        return GetACAUIBusinessHeader(DocIntf);
    };

    _di_IXMLTransmitterACAUIBusinessHeaderType __fastcall LoadACAUIBusinessHeader(const System::UnicodeString& FileName)
    {
        return (_di_IXMLTransmitterACAUIBusinessHeaderType) Xml::Xmldoc::LoadXMLDocument(FileName)->GetDocBinding("ACAUIBusinessHeader", __classid(TXMLTransmitterACAUIBusinessHeaderType), eACA_UI_Header_TargetNamespace);
    };

    _di_IXMLTransmitterACAUIBusinessHeaderType __fastcall  NewACAUIBusinessHeader()
    {
        return (_di_IXMLTransmitterACAUIBusinessHeaderType) Xml::Xmldoc::NewXMLDocument()->GetDocBinding("ACAUIBusinessHeader", __classid(TXMLTransmitterACAUIBusinessHeaderType), eACA_UI_Header_TargetNamespace);
    };

    // TXMLTransmitterACAUIBusinessHeaderType

    void __fastcall TXMLTransmitterACAUIBusinessHeaderType::AfterConstruction(void)
    {
        RegisterChildNode(System::UnicodeString("ACABusinessHeader"), __classid(TXMLACABulkBusinessHeaderRequestType_air7_0), "urn:us:gov:treasury:irs:common");
        RegisterChildNode(System::UnicodeString("ACATransmitterManifestReqDtl"), __classid(TXMLACATrnsmtManifestReqDtlType_air7_0));
        Xml::Xmldoc::TXMLNode::AfterConstruction();
    };

    UnicodeString __fastcall TXMLTransmitterACAUIBusinessHeaderType::Get_irs_NS()
    {
        return TXMLNode::AttributeNodes->Nodes[UnicodeString("xmlns:irs")]->Text;
    };

    void __fastcall TXMLTransmitterACAUIBusinessHeaderType::Set_irs_NS(UnicodeString Value)
    {
        //TXMLNode::SetAttributeNS(UnicodeString("xmlns:irs"), "", Value);
        TXMLNode::DeclareNamespace(UnicodeString("irs"), Value);
    };
// More of the same

这是我编写的一些初步代码,用于使用该类测试输出:

Manifest = new TXMLDocument(GetWindow());
        Manifest->DOMVendor = GetDOMVendor("MSXML"); // NOT cross platform compatible
        Manifest->NodeIndentStr = char(9); // TAB character
        Manifest->Options = Manifest->Options << doNodeAutoIndent << doAttrNull << doAutoPrefix;

        Manifest_root = GetACAUIBusinessHeader(Manifest);

        Manifest->Version = "1.0";
        Manifest->Encoding = "UTF-8";

        // Assign NameSpaces and Schema
        Manifest_root->irs_NS = "urn:us:gov:treasury:irs:common";
        Manifest_root->xsi_NS = "http://www.w3.org/2001/XMLSchema-instance";
        Manifest_root->acabushdr_NS = "urn:us:gov:treasury:irs:msg:acabusinessheader";
        Manifest_root->h1_NS = "urn:us:gov:treasury:irs:msg:acauibusinessheader";
        Manifest_root->schemaLocation = "urn:us:gov:treasury:irs:msg:acauibusinessheader IRS-ACAUserInterfaceHeaderMessage.xsd";

        Manifest_root->ACABusinessHeader->UniqueTransmissionId = "token"; // Just for testing
        Manifest_root->ACABusinessHeader->Timestamp = "2001-12-17T09:30:47Z"; // Just for testing

        Manifest_root->ACATransmitterManifestReqDtl->PaymentYr = "2016";
        Manifest_root->ACATransmitterManifestReqDtl->PriorYearDataInd = "1";
        Manifest_root->ACATransmitterManifestReqDtl->EIN = "000000000";

如果我在上面的代码中取出 RegisterChildNode() 方法的第三个参数,它不会崩溃,但输出不正确:

<?xml version="1.0" encoding="UTF-8"?>
<ACAUIBusinessHeader xmlns="urn:us:gov:treasury:irs:ext:aca:air:7.0" xmlns:irs="urn:us:gov:treasury:irs:common" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:acabushdr="urn:us:gov:treasury:irs:msg:acabusinessheader" xmlns:h1="urn:us:gov:treasury:irs:msg:acauibusinessheader" xsi:schemaLocation="urn:us:gov:treasury:irs:msg:acauibusinessheader IRS-ACAUserInterfaceHeaderMessage.xsd">
    <ACABusinessHeader>
        <UniqueTransmissionId>token</UniqueTransmissionId>
        <Timestamp>2001-12-17T09:30:47Z</Timestamp>
    </ACABusinessHeader>
    <ACATransmitterManifestReqDtl>
        <PaymentYr>2016</PaymentYr>
        <PriorYearDataInd>1</PriorYearDataInd>
        <EIN>000000000</EIN>
    </ACATransmitterManifestReqDtl>
</ACAUIBusinessHeader>

如您所见,缺少根节点 ACAUIBusinessHeader、ACABusinessHeader 节点以及 Timestamp & EIN 节点所需的前缀(命名空间),而且我不知道如何正确调整类来分配它们。

4

1 回答 1

1

我终于能够弄清楚如何调整生成的 XML 类以获得所需的输出。我将 DeclareNamespace() 调用移至 AfterConstruction() 函数,并且必须为那些使用不同命名空间的节点更改 Get() 函数调用(以及适用时的 Set())。

这是改编代码的第一部分:

_di_IXMLTransmitterACAUIBusinessHeaderType __fastcall GetACAUIBusinessHeader(Xml::Xmlintf::_di_IXMLDocument Doc)
{
    return (_di_IXMLTransmitterACAUIBusinessHeaderType) Doc->GetDocBinding("n1:ACAUIBusinessHeader", __classid(TXMLTransmitterACAUIBusinessHeaderType), nsN1);
};

_di_IXMLTransmitterACAUIBusinessHeaderType __fastcall GetACAUIBusinessHeader(Xml::Xmldoc::TXMLDocument *Doc)
{
    Xml::Xmlintf::_di_IXMLDocument DocIntf;
    Doc->GetInterface(DocIntf);
    return GetACAUIBusinessHeader(DocIntf);
};

_di_IXMLTransmitterACAUIBusinessHeaderType __fastcall LoadACAUIBusinessHeader(const System::UnicodeString& FileName)
{
    return (_di_IXMLTransmitterACAUIBusinessHeaderType) Xml::Xmldoc::LoadXMLDocument(FileName)->GetDocBinding("n1:ACAUIBusinessHeader", __classid(TXMLTransmitterACAUIBusinessHeaderType), nsN1);
};

_di_IXMLTransmitterACAUIBusinessHeaderType __fastcall  NewACAUIBusinessHeader()
{
    return (_di_IXMLTransmitterACAUIBusinessHeaderType) Xml::Xmldoc::NewXMLDocument()->GetDocBinding("n1:ACAUIBusinessHeader", __classid(TXMLTransmitterACAUIBusinessHeaderType), nsN1);
};

// TXMLTransmitterACAUIBusinessHeaderType

void __fastcall TXMLTransmitterACAUIBusinessHeaderType::AfterConstruction(void)
{
    TXMLNode::DeclareNamespace(System::UnicodeString(""), nsACA); // default xmlns
    TXMLNode::DeclareNamespace(System::UnicodeString("irs"), nsIRS);
    TXMLNode::DeclareNamespace(System::UnicodeString("xsi"), nsXSI);
    TXMLNode::DeclareNamespace(System::UnicodeString("acabushdr"), nsACAbushdr);
    TXMLNode::DeclareNamespace(System::UnicodeString("n1"), nsN1);
    RegisterChildNode(System::UnicodeString("ACABusinessHeader"), __classid(TXMLACABulkBusinessHeaderRequestType_air7_0), nsACAbushdr);
    RegisterChildNode(System::UnicodeString("ACATransmitterManifestReqDtl"), __classid(TXMLACATrnsmtManifestReqDtlType_air7_0), nsACA);
    TXMLNode::SetAttribute(System::UnicodeString("xsi:schemaLocation"), SchemaLoc);
    Xml::Xmldoc::TXMLNode::AfterConstruction();
};

_di_IXMLACABulkBusinessHeaderRequestType_air7_0 __fastcall TXMLTransmitterACAUIBusinessHeaderType::Get_ACABusinessHeader()
{
    _di_IXMLACABulkBusinessHeaderRequestType_air7_0 result = GetChildNodes()->FindNode("acabushdr:ACABusinessHeader", nsACAbushdr);
    if(result == NULL)
        result = GetChildNodes()->Nodes[System::UnicodeString("acabushdr:ACABusinessHeader")]; // creates it
    return result;
};

_di_IXMLACATrnsmtManifestReqDtlType_air7_0 __fastcall TXMLTransmitterACAUIBusinessHeaderType::Get_ACATransmitterManifestReqDtl()
{
    _di_IXMLACATrnsmtManifestReqDtlType_air7_0 result = GetChildNodes()->FindNode("ACATransmitterManifestReqDtl", nsACA);
    if(result == NULL) // Because this XML document doesn't use the default xmlns for the "root" node, but this node DOES use the default xmlns, it has to be added this way to match up the namespace
        result = AddChild("ACATransmitterManifestReqDtl", nsACA); // creates it
    return result;
};

“nsACA”和它的表兄弟只是常量 UnicodeStrings。如您所见,我还必须在 GetDocBinding() 调用中将“n1:”前缀/命名空间添加到根节点的名称中。命名空间稍后在 AfterConstruction() 函数中声明。对于使用“irs:”前缀/命名空间的节点,只需在 AfterConstruction() 函数中声明节点字符串名称后将其添加到节点字符串名称中就足够了。这是一个例子:

System::UnicodeString __fastcall TXMLACABulkBusinessHeaderRequestType_air7_0::Get_Timestamp()
{
    return GetChildNodes()->Nodes[System::UnicodeString("irs:Timestamp")]->NodeValue.operator System::UnicodeString();
};

void __fastcall TXMLACABulkBusinessHeaderRequestType_air7_0::Set_Timestamp(System::UnicodeString Value)
{
    GetChildNodes()->Nodes[System::UnicodeString("irs:Timestamp")]->NodeValue = Value;
};

当其中一个子节点没有从父节点继承它的命名空间并且使用默认的 xmlns 命名空间(没有像“irs:”示例这样的前缀)时,会涉及更多内容。这是我为 UniqueTransmissionId 节点处理这种情况的方法:

System::UnicodeString __fastcall TXMLACABulkBusinessHeaderRequestType_air7_0::Get_UniqueTransmissionId()
{
    _di_IXMLNode result = GetChildNodes()->FindNode("UniqueTransmissionId", nsACA);
    if(result == NULL)
        return EmptyStr;
    return result->NodeValue.operator System::UnicodeString();
    //return GetChildNodes()->Nodes[System::UnicodeString("UniqueTransmissionId")]->NodeValue.operator System::UnicodeString();
};

void __fastcall TXMLACABulkBusinessHeaderRequestType_air7_0::Set_UniqueTransmissionId(System::UnicodeString Value)
{
    _di_IXMLNode result = GetChildNodes()->FindNode("UniqueTransmissionId", nsACA);
    if(result == NULL) // Because this XML document doesn't use the default xmlns for the "root" node, but this node DOES use the default xmlns, it has to be added this way to match up the namespace
        result = AddChild("UniqueTransmissionId", nsACA); // creates it
    result->NodeValue = Value;
    //GetChildNodes()->Nodes[System::UnicodeString("UniqueTransmissionId")]->NodeValue = Value;
};

这是最终输出:

<?xml version="1.0" encoding="UTF-8"?>
<n1:ACAUIBusinessHeader xmlns="urn:us:gov:treasury:irs:ext:aca:air:7.0" xmlns:irs="urn:us:gov:treasury:irs:common" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:acabushdr="urn:us:gov:treasury:irs:msg:acabusinessheader" xmlns:n1="urn:us:gov:treasury:irs:msg:acauibusinessheader" xsi:schemaLocation="urn:us:gov:treasury:irs:msg:acauibusinessheader IRS-ACAUserInterfaceHeaderMessage.xsd">
    <acabushdr:ACABusinessHeader>
        <UniqueTransmissionId>token</UniqueTransmissionId>
        <irs:Timestamp>2001-12-17T09:30:47Z</irs:Timestamp>
    </acabushdr:ACABusinessHeader>
    <ACATransmitterManifestReqDtl>
        <PaymentYr>2016</PaymentYr>
        <PriorYearDataInd>1</PriorYearDataInd>
        <irs:EIN>000000000</irs:EIN>
    </ACATransmitterManifestReqDtl>
</n1:ACAUIBusinessHeader>

希望这对使用 Delphi/C++ Builder XML 数据绑定向导的任何人都有帮助。看起来它只能自己处理一个命名空间,但是通过这些类型的更改,它仍然是一个很好的起点。

于 2016-07-11T23:00:11.607 回答