2010-10-21 102 views
3

我使用的XML綁定向導來創建TXMLDocument的後裔每個節點。這個類生成的文件將在根節點中聲明命名空間,併爲文檔的其餘部分創建純粹的未經修改的節點。如何命名空間前綴添加到使用TXMLDocument的

<?xml version="1.0"?> 
<RootNode xmlns="URL" xmlns:xsi="URL" xsi:schemaLocation="URL"> 
    <SomeNode> 
     <AnotherNode>Value</AnotherNode> 
    </SomeNode> 
</RootNode> 

我已經沒有任何困難的閱讀或驗證這一點。但是,現在要發送這些文件的處理器要求每個節點都有名稱空間前綴以正確處理文件。

<?xml version="1.0"?> 
<NS:RootNode xmlns:NS="URL" xmlns:xsi="URL" xsi:schemaLocation="URL"> 
    <NS:SomeNode> 
     <NS:AnotherNode>Value</NS:AnotherNode> 
    </NS:SomeNode> 
</NS:RootNode> 

如何用我的TXMLDocument後裔完成此操作?我希望它不涉及手動編輯10000行生成的代碼。

+0

對不起,我一定是誤解了什麼 – mjn 2014-05-14 07:59:27

回答

5

O k,解決方案需要很長時間才能發現,但出人意料的簡單。

通過XML數據綁定向導將使用默認的命名空間創建XML生成的代碼。您可以在生成的單位檢查GetLoadNew功能的看到這一點。所有這三個撥打電話到GetDocBinding,在TargetNamespace傳遞作爲最後一個參數。 TargetNamespace是一個全局常量字符串與URI從你送入綁定向導模式或XML文檔中提取。

因爲TargetNamespace被分配到根元素作爲默認命名空間沒有子元素將有一個前綴。

的方式做到這一點:

FDocumentName := 
    NewXMLDocument.GetDocBinding(
    'ns:DocumentName', // <-- Just add the prefix to the root node. 
    TXMLDocumentName, 
    TargetNamespace) as IXMLDocumentName; 

現在根節點的樣子:

<ns:DocumentName xmlns:ns="URI"> 

和所有子節點將具有前綴在創建時。

-1

add namespace + prefix to XML using XSL

接受的答案顯示XSL如何使用添加命名空間前綴。

報價:


使用

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:login="http://my.ns.uri"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="*"> 
    <xsl:element name="login:{name()}" namespace="http://my.ns.uri"> 
    <xsl:copy-of select="namespace::*"/> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:element> 
</xsl:template> 
</xsl:stylesheet> 

當這種變換所提供的XML文檔應用,想要的,正確的結果產生

<login:data xmlns:login="http://my.ns.uri"> 
    <login:token> 
     <login:sessionId>12345</login:sessionId> 
     <login:userId>john</login:userId> 
     <login:moreInfo> 
     <login:bla> ..... 
     </login:bla> 
     </login:moreInfo> 
    </login:token> 
</login:data> 
0

除了上面的答案之外,有時您可能需要命名空間前綴以繼續重複子節點(使用Add()或Insert()函數創建的類型)。在這種情況下,您需要在RegisterChildNode()的第一個參數和ItemTag變量的子類名稱前面添加前綴和冒號以匹配。(見下面的例子,用「CPR:」被用作命名空間前綴)

void __fastcall TXMLeCPR_payrollInfo_employees::AfterConstruction(void) 
{ 
    RegisterChildNode(System::UnicodeString("CPR:employee"), __classid(TXMLeCPR_payrollInfo_employees_employee)); 
    ItemTag = "CPR:employee"; 
    ItemInterface = __uuidof(IXMLeCPR_payrollInfo_employees_employee); 
    Xml::Xmldoc::TXMLNodeCollection::AfterConstruction(); 
}; 
1

可能的解決方法與多個命名空間的問題:鉤子和類幫手

// 
// The original Delphi code is : XMLHookUnit.pas released 2015.09.20 
// Last version: 0.1 released 2015.09.20 
// The initial developer is Cedomir Plavljanic ([email protected]) 
// Copyright (C) 2015-2015 Cedomir Plavljanic 
// 
// This program is free software; you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation; either version 2 of the License, or 
// (at your option) any later version 
// 
// This unit is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
// GNU General Public License for more details. 
// 
// 
// This unit hooking 2 methods from XMLDoc.TXMLNode and 1 method from XMLDoc.TXMLNodeList 
// Allows use of units created with XML binding wizard with multiple namespace 
// 
// This is only test 
// 
//  XML Binding Wizard 
//   - change all the names that end with _ (All signature nodes have this problem) 
//   - example: TSignatureType_ -> TSignatureType_ds 
// 
// Usage: add the unit to project 
// 
// This unit contains variables 
// - ListNameSpace - dictionary for pair prefixes and namespace 
//   - in example pair is from XML Schema Definition in UBL 2.1 by Oasis 
//   http://docs.oasis-open.org/ubl/os-UBL-2.1/UBL-2.1.html 
//   - for own use must changed 
// - DigitalSignatureWithoutPrefix - flag for add or remove digital signature prefix in nodename 
// 
// 
// This unit contains Helper: TXMLNodeListHelper, TXMLNodeHelper 
// This unit contains function for hooking TXMLNode and TXMLNodeList 
// For hooking in testing using example from Hook Api Library 0.2 [Ring3] By Anskya Email:[email protected] 
// - with litle modification in call function VirtualProtect 
//  - flNewProtect used as PAGE_READWRITE 
// 
// version: 0.1 
// can be used with all versions of Delphi that have suport generic TDictionary 
// for older versions of Delphi have to ask via e-mail or add support for TDictionary 
// I also have a version for Delphi 2007 (XML binding wizard is bad, must be used from newer version of Delphi) 
// 


unit XMLHookUnit; 

interface 

uses 
    System.Generics.Collections; 

var 
////Dictionary for pair prefixes and namespaces in all *.xsd file (without default namespace) 
    ListNameSpace : TDictionary<String, String>; 
//Include or Exclude ds: prefix in digital signature node 
    DigitalSignatureWithoutPrefix : Boolean = True; 

//Hook 1 methods from TXMLNodeList and 2 method from TXMLNode 
//TXMLNodeList.GetNode 
//TXMLNode.RegisterChildNode 
//TXMLNode.InternalAddChildNode 
//for hooking in testing using example from Hook Api Library 0.2 [Ring3] By Anskya Email:[email protected] 
//with litle modification in call function VirtualProtect 
//flNewProtect is PAGE_READWRITE 
procedure HookXMLNodeLibrary; 
//UnHook 1 methods from TXMLNodeList and 2 method from TXMLNode 
//TXMLNodeList.GetNode 
//TXMLNode.RegisterChildNode 
//TXMLNode.InternalAddChildNode 
//for unhooking in testing using example from Hook Api Library 0.2 [Ring3] By Anskya Email:[email protected] 
//with litle modification in call function VirtualProtect 
//flNewProtect is PAGE_READWRITE 
procedure UnHookXMLNodeLibrary; 

implementation 

uses 
    System.Types, StrUtils, Variants, HookApiLib, xmldom, XMLDoc, XMLIntf; 

const 
//namespace for digital signature 
    NameSpace_DigitalSignature = 'http://www.w3.org/2000/09/xmldsig#'; 

var 
//Flag is True if methods from XMLDoc are hooked 
    IsHookXMLNodeLibrary : Boolean = False; 

type 
//access to proteted part in TXMLNodeList 
    TXMLNodeListHelp = class(TXMLNodeList); 
//access to proteted part in TXMLNode 
    TXMLNodeHelp = class(TXMLNode); 

//helper for TXMLNodelist 
    TXMLNodeListHelper = class helper for TXMLNodeList 
    public 
//avoid overload trouble 
//getnode call wrong findnode function 
    function FindNodeHelp(aField: DOMString):IXMLNode; 
//find prefix for node in ListNameSpace 
    function FindPrefixHelp(aField:DOMString):String; 
    end; 

//helper function for TXMLNodelist 
    TXMLNodeHelper = class helper for TXMLNode 
    public 
//extract LocalName, Prefix and Namespace based on NodeName 
    procedure ExtractFieldPrefixNameSpace(const aNodeName: DOMString; out aField, aPrefix, aNameSpace: DOMString); 
    end; 

//prototype for hooking TXMLNodeList.GetNode 
    TProtoTypeNodeListGetNode = function(const aSelf:TXMLNodeListHelp; 
             const IndexOrName: OleVariant): IXMLNode; 
//prototype for hooking TXMLNode.RegisterChildNode 
    TProtoTypeNodeRegisterChildNode = procedure(const aSelf:TXMLNodeHelp; 
               const aField: DOMString; 
               const ChildNodeClass: TXMLNodeClass; 
               const aNameSpace : DOMString); 
//prototype for hooking TXMLNode.InternalAddChild 
    TProtoTypeNodeInternalAddChild = function(const aSelf:TXMLNodeHelp; 
              const NodeClass: TXMLNodeClass; 
              const NodeName, NamespaceURI: DOMString; 
              const Index: Integer): IXMLNode; 

var 
//Save old address for TXMLNodeList.GetNode 
    SavePrototypeGetNode : TProtoTypeNodeListGetNode = nil; 
//Save old address for TXMLNode.RegisterChildNode 
    SaveProtoTypeRegisterChildNode : TProtoTypeNodeRegisterChildNode = nil; 
//Save old address for TXMLNode.InternalAddChild 
    SaveProtoTypeNodeInternalAddChild : TProtoTypeNodeInternalAddChild = nil; 

{ TXMLNodeListHelper } 

function TXMLNodeListHelper.FindNodeHelp(aField: DOMString): IXMLNode; 

var 
    aPrefix: string; 

begin 
    aPrefix := FindPrefixHelp(aField); 
    if aPrefix <> '' then Result := FindNode(aPrefix+':'+aField, ''); 
    if Result = nil then Result := FindNode(aField, ''); 
end; 

function TXMLNodeListHelper.FindPrefixHelp(aField: DOMString): String; 

var 
    aNodeClass:TNodeClassArray; 
    i: Integer; 
    aTest:TPair<String,String>; 

begin 
    Result := ''; 
    aNodeClass := TXMLNodeHelp(Self.Owner).ChildNodeClasses; 
    aField:=ExtractLocalName(aField); 
    for i := 0 to Length(aNodeClass)-1 do 
    if aNodeClass[i].NodeName = aField then begin 
     for aTest in ListNameSpace do begin 
     if aTest.Value = aNodeClass[i].NamespaceURI then begin 
      Result := aTest.Key; 
      Break; 
     end; 
     end; 
     Break; 
    end; 
end; 

{ TXMLNodeHelper } 
procedure TXMLNodeHelper.ExtractFieldPrefixNameSpace(const aNodeName : DOMString; out aField, aPrefix, aNameSpace: DOMString); 
var 
    i: Integer; 
    sHelp:DOMString; 
    Test:TPair<String,String>; 
    Flag : Boolean; 

begin 
    sHelp := ExtractLocalName(aNodeName); 
    aPrefix := ''; 
    aNameSpace := ''; 
    Flag := False; 
    for i := 0 to Length(ChildNodeClasses) - 1 do begin 
    if ChildNodeClasses[i].NodeName = sHelp then begin 
     aNameSpace := ChildNodeClasses[i].NamespaceURI; 
     for Test in ListNameSpace do begin 
     if Test.Value = aNameSpace then begin 
      aPrefix := Test.Key; 
      Flag := DigitalSignatureWithoutPrefix and (aNameSpace = NameSpace_DigitalSignature); 
      Break; 
     end; 
     end; 
     Break; 
    end; 
    end; 
    if (aPrefix = '') or (Flag) then begin 
    aField := ExtractLocalName(aNodeName); 
    if aNameSpace = '' then aNameSpace := GetNamespaceURI; 
    end else 
    aField := aPrefix + ':' + ExtractLocalName(aNodeName); 
end; 


//help function for find namaspase bassed on classname 
//last part after underscore in classname is prefix 
function GetNameSpace(const ChildNodeClass: TXMLNodeClass): DOMString; 

var 
    aList : TStringDynArray; 

begin 
    Result := ChildNodeClass.ClassName; 
    aList:=StrUtils.SplitString(Result,'_'); 
    if Length(aList)>1 then 
    ListNameSpace.TryGetValue(aList[Length(aList)-1],Result) 
    else 
    Result := ''; 
end; 

//replace for TXMLNodeList.GetNode 
function GetNodeHelp(const aSelf:TXMLNodeListHelp; 
         const IndexOrName: OleVariant):IXMLNode; 

begin 
    if VarIsOrdinal(IndexOrName) then 
    Result := SavePrototypeGetNode(aSelf,IndexOrName) 
    else begin 
    Result := aSelf.FindNodeHelp(DOMString(IndexOrName)); 
    if Result = nil then 
     Result := SavePrototypeGetNode(aSelf,IndexOrName); 
    end; 
end; 

//replace for TXMLNode.RegisterChildNode 
procedure RegisterChildNodeHelp(const aSelf:TXMLNodeHelp; 
           const aField: DOMString; 
           const ChildNodeClass: TXMLNodeClass; 
           const aNameSpace : DOMString); 

var 
    hNameSpace: DOMString; 

begin 
    if aNameSpace<>'' then 
    hNameSpace := aNameSpace 
    else begin 
    hNameSpace := GetNameSpace(ChildNodeClass); 
    if hNameSpace = '' then hNameSpace := aSelf.GetNamespaceURI; 
    end; 
    SaveProtoTypeRegisterChildNode(aSelf, aField, ChildNodeClass, hNameSpace); 
end; 

//replace for TXMLNode.InternalAddChild 
function InternalAddChildHelp(const aSelf:TXMLNodeHelp; 
           const NodeClass: TXMLNodeClass; 
           const NodeName, NamespaceURI: DOMString; 
           const Index: Integer): IXMLNode; 

var 
    aField, aPrefix, aNameSpace:DOMString; 

begin 
    aSelf.ExtractFieldPrefixNameSpace(NodeName, aField, aPrefix, aNameSpace); 
    Result := SaveProtoTypeNodeInternalAddChild(aSelf, NodeClass, aField, aNameSpace, Index); 
end; 


procedure HookXMLNodeLibrary; 

begin 
    if IsHookXMLNodeLibrary then Exit; 

    @SavePrototypeGetNode := HookCode(@TXMLNodeListHelp.GetNode, @GetNodeHelp); 
    @SaveProtoTypeRegisterChildNode := HookCode(@TXMLNodeHelp.RegisterChildNode, @RegisterChildNodeHelp); 
    @SaveProtoTypeNodeInternalAddChild := HookCode(@TXMLNodeHelp.InternalAddChild, @InternalAddChildHelp); 
    IsHookXMLNodeLibrary := True; 
end; 

procedure UnHookXMLNodeLibrary; 

begin 
    if not IsHookXMLNodeLibrary then Exit; 

    UnHookCode(@SavePrototypeGetNode); 
    UnHookCode(@SaveProtoTypeRegisterChildNode); 

    UnHookCode(@SaveProtoTypeNodeInternalAddChild); 

    SavePrototypeGetNode := nil; 
    SaveProtoTypeRegisterChildNode := nil; 
    SaveProtoTypeNodeInternalAddChild := nil; 

    IsHookXMLNodeLibrary := False; 
end; 

//Dictionary for prefixes and namespaces 
procedure AddNameSpace; 

begin 
    ListNameSpace.Add('xsd','http://www.w3.org/2001/XMLSchema'); 
    ListNameSpace.Add('cac','urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2'); 
    ListNameSpace.Add('cbc','urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2'); 
    ListNameSpace.Add('ccts','urn:un:unece:uncefact:documentation:2'); 
    ListNameSpace.Add('ext','urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2'); 
    ListNameSpace.Add('udt','urn:oasis:names:specification:ubl:schema:xsd:UnqualifiedDataTypes-2'); 
    ListNameSpace.Add('qdt','urn:oasis:names:specification:ubl:schema:xsd:QualifiedDataTypes-2'); 
    ListNameSpace.Add('ccts-cct','urn:un:unece:uncefact:data:specification:CoreComponentTypeSchemaModule:2'); 
    ListNameSpace.Add('cct','urn:un:unece:uncefact:data:specification:CoreComponentTypeSchemaModule:2'); 
    ListNameSpace.Add('sig','urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2'); 
    ListNameSpace.Add('sac','urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2'); 
    ListNameSpace.Add('ds','http://www.w3.org/2000/09/xmldsig#'); 
    ListNameSpace.Add('sbc','urn:oasis:names:specification:ubl:schema:xsd:SignatureBasicComponents-2'); 
    ListNameSpace.Add('xsi','http://www.w3.org/2001/XMLSchema-instance'); 

end; 

initialization 
    HookXMLNodeLibrary; 
    ListNameSpace := TDictionary<String,String>.Create; 
    AddNameSpace; 
finalization 
    UnHookXMLNodeLibrary; 
    ListNameSpace.DisposeOf; 
end. 
相關問題