2013-08-23 8 views
1

구성 데이터를 XML 파일에 쓰려고합니다. 그러나 XML은 매우 구조화 보이거나 어떻게 그것을XML을 직렬화 할 때 각 속성을 자체 행에 어떻게 가져 옵니까?

<Configuration> 
    <Ftp 
     Host="LOCALHOST" 
     Port="21" 
    /> 
    <Pop3 
     Host="LOCALHOST" 
     Port="110" 
     Interval="30000" 
    /> 
    <Smtp 
     Host="LOCALHOST" 
     Port="25" 
    /> 
</Configuration> 

같이하고 싶은

<Configuration> 
    <Ftp Host="LOCALHOST" Port="21"/> 
    <Pop3 Host="LOCALHOST" Port="110" Interval="30000"/> 
    <Smtp Host="LOCALHOST" Port="25"/> 
</Configuration> 

말할 수 여기에 어떤 식 으로든 이 내 델파이 코드의 조각이라는 것이다 수 있습니다. 모든 유형의 함수/프로 시저가 있지만 여기에 2를 표시합니다.

constructor TConnXml.Create(const FileName: string); 
begin 
    inherited Create; 
    fConfigfile  := FileName; 
    fXMLDoc   := TXMLDocument.Create(Application); 
    fXMLDoc.Options := [doNodeAutoIndent]; 
    if FileExists(fConfigfile) then 
    fXMLDoc.LoadFromFile(fConfigfile) 
    else 
    begin 
     fXMLDoc.Active := True; 
     fXMLDoc.AddChild('Configuration'); 
     fXMLDoc.SaveToFile(fConfigfile); 
    end; 
end; 

constructor TConnXml.Create; 
begin 
    Create(SettingsFileBuild); 
end; 

function TConnXml.ReadString(const Section, Key, Default: string): string; 
var 
    Node: IXMLNode; 
begin 
    Node := fXMLDoc.DocumentElement.ChildNodes.FindNode(Section); 
    if Assigned(Node) and Node.HasAttribute(Key) then 
    Result := Node.Attributes[Key] 
    else 
    Result := Default; 
end; 

procedure TConnXml.WriteString(const Section, Key, Value: string); 
var 
    Node: IXMLNode; 
begin 
    if ReadString(Section, Key, '') = Value then 
    Exit; 
    Node := fXMLDoc.DocumentElement.ChildNodes.FindNode(Section); 
    if not Assigned(Node) then 
    Node := fXMLDoc.DocumentElement.AddChild(Section); 
    Node.Attributes[Key] := Value; 
    fModified := True; 
    Save; 
end; 

procedure TConnXml.Save; 
begin 
    if not fModified then 
    Exit; 
    if fBackup then 
    CopyFile(PChar(fConfigfile), PChar(fConfigfile + '.bak'), False); 
    fXMLDoc.Active := True; 
    fXMLDoc.SaveToFile(fConfigfile); 
    fModified := False; 
end; 

function TConnXml.ReadBoolean(const Section, Key: string; Default: Boolean): Boolean; 
begin 
    Result := Boolean(ReadInteger(Section, Key, Integer(Default))); 
end; 

procedure TConnXml.WriteBoolean(const Section, Key: string; Value: Boolean); 
begin 
    WriteInteger(Section, Key, Integer(Value)); 
end; 
+5

xml의 주된 목적은 사람이 읽을 수 없도록하는 것입니다. 그것은 기계 - 기계 통신을위한 것입니다. 귀하의 출력물은 "올바른"형식화 된 XML 출력이어야합니다. 왜 다른 모습이 필요한거야? XmlWith 이외의 다른 것을 "보기"원한다면, 자신의 XmlWriter를 작성해야만합니다. 그렇지 않으면 다른 형식으로 변경해야합니다. – Alex

+0

대신 [TIniFile] (http://delphi.about.com/od/objectpascalide/a/tinifile.htm)을 사용해보십시오. '.ini' 파일 구조에서 설정을 편집하는 사람이 잘못된 것을 얻는 반면 XML은 * syntax-heavy * 일 가능성이 훨씬 적습니다. –

+1

대신 YAML을 사용하여 더 멋지게 보이게하십시오 –

답변

2

이 XML을 생성하고 구성 목적으로 사용하는 경우 더 읽기 쉽도록 만드는 것이 그 목적입니다. 구성을 위해 XML을 많이 사용하며 실제로 적용 할 수있는 경우에만 속성을 사용합니다.

나는이처럼 작성합니다

<Configuration> 
    <Ftp> 
    <Host>LOCALHOST</Host> 
    <Port>25</Port> 
    </Ftp> 
    <Pop3> 
    <Host>LOCALHOST/<Host> 
    <Port>110</Port> 
    <Interval>30000</Interval> 
    </Pop> 
    <Smtp> 
    <Host>LOCALHOST</Host> 
    <Port>25</Port> 
    </Smtp> 
</Configuration> 

다음, XML을 다른 형식을 사용하여, 또한 솔루션입니다. 그러나 XML을 고수한다면, 필자의 대답은 사람이 읽을 수있는 방식으로 XML을 구성하는 한 가지 방법입니다. 또한 특성을 사용하지 않으면 JSON으로의 변환이 매우 간단합니다.

XML이 마크 업으로 부 풀지 만 잘 구조화되어 있으면 읽을 수 있습니다. 컴퓨터 데이터 교환을위한 것이기는하지만 구성 파일에 매우 유용합니다. YAML은 잘 보이지만, 나를 위해 그것을 명시 적 구조 :

업데이트하는 것이 부족 :

때문에 나는 추가 정보와 답을 갱신 코드에 대한 요청에. 광산처럼 XML을 얻으려면 한 가지 절차 만 변경하면됩니다. 반면에 이것은 기본적인 XML 처리이므로 익히 게하십시오.

function TConnXml.ReadString(const Section, Key, Default: string): string; 
var 
    Node: IXMLNode; 
    Child: IXMLNode; 
begin 
    Node := fXMLDoc.DocumentElement.ChildNodes.FindNode(Section); 

    if not Assigned(Node) then 
    begin 
    Result := Default; 
    Exit; 
    end; 

    Child:= Node.FindNode(Key); 

    if not Assigned(Child) then 
    begin 
    Result := Default; 
    Exit; 
    end; 

    Result := Child.Text; 
end; 

procedure TConnXml.WriteString(const Section, Key, Value: string); 
var 
    Node: IXMLNode; 
    Child: IXMLNode; 
begin 
    if ReadString(Section, Key, '') = Value then 
    Exit; 

    Node := fXMLDoc.DocumentElement.ChildNodes.FindNode(Section); 

    if not Assigned(Node) then 
    Node := fXMLDoc.DocumentElement.AddChild(Section); 

    Child:= Node.ChildNodes.FindNode(Key); 

    if not Assigned(Child) then 
    Child:= Node.AddChild(Key); 

    Child.Text := Value; 
    fModified := True; 
    Save; 
end; 

테스트하지 않고 작성 했으므로 오류가있을 수 있지만 사용해야하는 코드입니다.

+0

YAML에는 구조가 부족합니다. –

+0

나는 그것을 빨리 다윗에게 썼다. 나는 YAML에 아무런 문제가 없다고 생각한다. 나는 단지 XML 명시 적 태깅 (< and > chars)에 익숙해졌으며, 실제로 그것 때문에 더 빨리 탐색한다. 그러나 그것은 저의 것입니다. 나는 YAML이 XML처럼 비 대한 것이 아니라는 것을 잘 알고 있습니다. – Runner

+0

@Runner 정확하게 내 파일을 보여주고 싶습니다. 그러나 나는 아직 그것을 어떻게하는지 알지 못했습니다. 누군가 샘플 코드를 가지고 있다면, 나는 한 번 보길 원합니다. – OZ8HP