【问题标题】:How to assign namespace and prefix to XML Nodes with C++ Builder如何使用 C++ Builder 为 XML 节点分配命名空间和前缀
【发布时间】:2016-07-09 00:25:32
【问题描述】:

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

这是我需要的 XML 输出的 sn-p:

<?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 时,当我尝试使用该节点的属性时它会崩溃。

这里是编辑类的代码sn-p:

    _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 节点所需的前缀(命名空间),我不知道如何正确调整类来分配它们。

【问题讨论】:

    标签: xml dom c++builder irs


    【解决方案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 数据绑定向导的任何人都有帮助。看起来它只能自己处理一个命名空间,但是通过这些类型的更改,它仍然是一个不错的起点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-27
      • 1970-01-01
      • 1970-01-01
      • 2010-11-23
      • 1970-01-01
      • 2014-08-17
      相关资源
      最近更新 更多