Seite 1 von 2

XML einlesen

Verfasst: 29.04.2012 21:56
von kunstlust
Ich möchte gerne eine XML eines Druckers auslesen und haben mir als Grundlage diesen Code als Hilfe genommen http://rosettacode.org/wiki/XML/Input#PureBasic
Ich verstehe nur noch nicht, wie ich zB. von "<JOB_NAME value='Pubebasic.pdf'/>" das Pubebasic.pdf in die "MessageRequester("ACCOUNTING_INFO", JOB_NAME\s)" bekommen und würde mich um hilfe sehr freuen.

Danke :D

Code: Alles auswählen

Define JOB_NAME.String, src$

src$ =  "<ACCOUNTING_INFO>"
src$ + "<JOB_NAME value='Pubebasic.pdf'/>"
src$ + "<UUID value='30384F30-3930-3037-4f8d-75db0000006c'/>"
src$ + "<USER_DEFINED value=''/>"
src$ + "<APPLICATION_ID value='PIDHPDRL000'/>"
src$ + "<ACCOUNT_ID value=''/>"
src$ + "<TIMESTAMP value='20120417155422'/>"
src$ + "<PRINTING_TIMESTAMP value='20120417155331'/>"
src$ + "<JOB_STATUS value='0'/>"
src$ + "<USER_NAME value=''/>"
src$ + "<SOURCE value='1'/>"
src$ + "<INK_COVERAGE_CATEGORY value='D'/>"
src$ + "<PRINT_QUALITY value='1'/>"
src$ + "<PRINT_TYPE value='1'/>"
src$ + "<PAGES value='1'/>"
src$ + "<COPIES value='1'/>"
src$ + "<PRINTING_TIME units='secondsx10' value='428'/>"
src$ + "<SCANNED_AREA units='sqi' value=''/>"
src$ + "<MEDIA_INFO>"
src$ + "<NAME vendor-name='' media-name='Plain Paper'/>"
src$ + "<QUANTITY units='sqi' value='96'/>"
src$ + "<SIZE units='inchesx3600'>"
src$ + "<WIDTH value='42112'/>"
src$ + "<LENGTH value='29782'/>"
src$ + "</SIZE><SOURCE value=''/>"
src$ + "</MEDIA_INFO><INK_INFO>"
src$ + "<INK_USED units='microliters' value='249'/>"
src$ + "<CONSUME color='Y' quantity='55' ink-type='non-HP Ink'/>"
src$ + "<CONSUME color='C' quantity='50' ink-type='non-HP Ink'/>"
src$ + "<CONSUME color='mk' quantity='103' ink-type='non-HP Ink'/>"
src$ + "<CONSUME color='dg' quantity='43' ink-type='non-HP Ink'/>"
src$ + "<CONSUME color='M' quantity='42' ink-type='non-HP Ink'/>"
src$ + "<CONSUME color='G' quantity='42' ink-type='non-HP Ink'/>"
src$ + "</INK_INFO>"
src$ + "</ACCOUNTING_INFO>"
 

Procedure get_values(*cur_node, nodeName$, attribute$, *valueResults.String)

  Protected result$
 
  While *cur_node
    If XMLNodeType(*cur_node) = #PB_XML_Normal
 
      result$ = GetXMLNodeName(*cur_node)
      If result$ = nodeName$
        If ExamineXMLAttributes(*cur_node)
          While NextXMLAttribute(*cur_node)
            If XMLAttributeName(*cur_node) = attribute$
              If *valueResults <> #Null
                *valueResults\s + XMLAttributeValue(*cur_node) + Chr(13) ;value + carriage-return
              EndIf 
            EndIf
          Wend
        EndIf
      EndIf 
 
    EndIf 
 
    get_values(ChildXMLNode(*cur_node), nodeName$, attribute$, *valueResults)
    *cur_node = NextXMLNode(*cur_node)
  Wend 
EndProcedure
 
CatchXML(0,@src$,Len(src$))
 
If IsXML(0)
  get_values(MainXMLNode(0), "ACCOUNTING_INFO", "JOB_NAME",@JOB_NAME)
  MessageRequester("ACCOUNTING_INFO", JOB_NAME\s)
  FreeXML(0)
EndIf 

Re: XML einlesen

Verfasst: 29.04.2012 23:56
von STARGÅTE
Du benutzt die Prozedur nicht richtig.

sowohl "ACCOUNTING_INFO" als auch "JOB_NAME" sind Knoten-Namen, und der Attribut-Name ist "value".

Ich würde an dieser Stelle gleich auf eines meiner Include verweisen: ImportXML - XML als Struktur-Variable laden und lesen

Damit kannst du die XML direkt als Struktur in PB nutzen.
Hier mal die nötigen Zeilen:

Code: Alles auswählen


;- Include

Enumeration
	#ImportXML_File
	#ImportXML_String
EndEnumeration

; Attribut-Name und Wert als Integer, Float und String
Structure XMLAttribute
	Name.s
	Integer.i
	Float.f
	StructureUnion
		Value.s
		String.s
	EndStructureUnion
EndStructure

; Knoten-Name, -Text und -Typ, sowie alle Unterknoten und Attribute
Structure XMLNode
	Name.s
	Text.s
	Type.i
	List *Attributes.XMLAttribute()
	Map Attribute.XMLAttribute(8) ; Aus Sparsamkeit nur 8 Slots
	List *Nodes.XMLNode()
	Map Node.XMLNode(16) ; Aus Sparsamkeit nur 16 Slots
EndStructure

; XML-Struktur mit Hauptknoten und Pfadzugriff
Structure XML
	Main.XMLNode
	Map *Path.XMLNode()
EndStructure

; Intern: Importieren eines XML-Knotens
Procedure ImportXML_Node(*XML.XML, *XMLNode.XMLNode, *Node)
	Protected *Child
	With *XMLNode
		\Type = XMLNodeType(*Node)
		\Name = GetXMLNodeName(*Node)
		\Text = GetXMLNodeText(*Node)
		AddMapElement(*XML\Path(), XMLNodePath(*Node))
		*XML\Path() = *XMLNode
		If ExamineXMLAttributes(*Node)
			While NextXMLAttribute(*Node)
				AddMapElement(\Attribute(), XMLAttributeName(*Node))
				AddElement(\Attributes())
				\Attributes() = @\Attribute()
				\Attribute()\Name    = XMLAttributeName(*Node)
				\Attribute()\String  = XMLAttributeValue(*Node)
				\Attribute()\Integer = Val(XMLAttributeValue(*Node))
				\Attribute()\Float   = ValF(XMLAttributeValue(*Node))
			Wend
		EndIf
		*Child = ChildXMLNode(*Node)
		While *Child
			AddMapElement(\Node(), GetXMLNodeName(*Child), #PB_Map_NoElementCheck)
			AddElement(\Nodes())
			\Nodes() = @\Node()
			ImportXML_Node(*XML, \Node(), *Child)
			*Child = NextXMLNode(*Child)
		Wend
	EndWith
EndProcedure

; Prozedur zum importieren einer XML-Datei als Variable mit Struktur
Procedure ImportXML(*XML.XML, Source.s, Type.i=#ImportXML_File)
	Protected XML.i, Result.i
	Select Type
		Case #ImportXML_File
			XML = LoadXML(#PB_Any, Source)
		Case #ImportXML_String
			XML = CatchXML(#PB_Any, @Source, StringByteLength(Source))
	EndSelect
	If XML
		If XMLStatus(XML) = #PB_XML_Success
			ImportXML_Node(*XML, *XML\Main, MainXMLNode(XML))
			Result = #True
		EndIf
		FreeXML(XML)
	EndIf
	ProcedureReturn Result
EndProcedure


Define Example.XML
Define src$

src$ =  "<ACCOUNTING_INFO>"
src$ + "<JOB_NAME value='Pubebasic.pdf'/>"
src$ + "<UUID value='30384F30-3930-3037-4f8d-75db0000006c'/>"
src$ + "<USER_DEFINED value=''/>"
src$ + "<APPLICATION_ID value='PIDHPDRL000'/>"
src$ + "<ACCOUNT_ID value=''/>"
src$ + "<TIMESTAMP value='20120417155422'/>"
src$ + "<PRINTING_TIMESTAMP value='20120417155331'/>"
src$ + "<JOB_STATUS value='0'/>"
src$ + "<USER_NAME value=''/>"
src$ + "<SOURCE value='1'/>"
src$ + "<INK_COVERAGE_CATEGORY value='D'/>"
src$ + "<PRINT_QUALITY value='1'/>"
src$ + "<PRINT_TYPE value='1'/>"
src$ + "<PAGES value='1'/>"
src$ + "<COPIES value='1'/>"
src$ + "<PRINTING_TIME units='secondsx10' value='428'/>"
src$ + "<SCANNED_AREA units='sqi' value=''/>"
src$ + "<MEDIA_INFO>"
src$ + "<NAME vendor-name='' media-name='Plain Paper'/>"
src$ + "<QUANTITY units='sqi' value='96'/>"
src$ + "<SIZE units='inchesx3600'>"
src$ + "<WIDTH value='42112'/>"
src$ + "<LENGTH value='29782'/>"
src$ + "</SIZE><SOURCE value=''/>"
src$ + "</MEDIA_INFO><INK_INFO>"
src$ + "<INK_USED units='microliters' value='249'/>"
src$ + "<CONSUME color='Y' quantity='55' ink-type='non-HP Ink'/>"
src$ + "<CONSUME color='C' quantity='50' ink-type='non-HP Ink'/>"
src$ + "<CONSUME color='mk' quantity='103' ink-type='non-HP Ink'/>"
src$ + "<CONSUME color='dg' quantity='43' ink-type='non-HP Ink'/>"
src$ + "<CONSUME color='M' quantity='42' ink-type='non-HP Ink'/>"
src$ + "<CONSUME color='G' quantity='42' ink-type='non-HP Ink'/>"
src$ + "</INK_INFO>"
src$ + "</ACCOUNTING_INFO>"

If ImportXML(@Example, src$, #ImportXML_String)
	MessageRequester("ACCOUNTING_INFO", Example\Main\Node("JOB_NAME")\Attribute("value")\String)
EndIf 


Re: XML einlesen

Verfasst: 30.04.2012 09:38
von kunstlust
Ich Danke dir sehr STARGÅTE, ich habe mir das auf dem Link von dir zuvor schon mal angeschaut, aber noch nicht ganz verstanden, nun denke ich schon.
Vielen Dank für deine Hilfe :bounce:

Re: XML einlesen

Verfasst: 30.04.2012 10:21
von kunstlust
Eine bescheidene Frage habe ich aber noch, wie lese ich solche Inhalte aus?

"<FW_Version>KHN_01_00_09.5</FW_Version>"

Code: Alles auswählen

Debug Example\Main\Node("FW_Version")......

Re: XML einlesen

Verfasst: 30.04.2012 11:07
von ts-soft

Code: Alles auswählen

If ImportXML(@Example, src$, #ImportXML_String)
   MessageRequester("ACCOUNTING_INFO", Example\Main\Node("FW_Version")\Text)
EndIf

Re: XML einlesen

Verfasst: 30.04.2012 11:28
von kunstlust
ts-soft leider ist kein Text zu sehen, die verschieden Typen habe ich auch schon probiert, was mache ich nur falsch? :praise:

Code: Alles auswählen

Define Example.XML
Define src$

src$ = "<FW_Version>KHN_01_00_09.5</FW_Version>"

If ImportXML(@Example, src$, #ImportXML_String)
   MessageRequester("FW_Version", Example\Main\Node("FW_Version")\Text)
EndIf


Re: XML einlesen

Verfasst: 30.04.2012 12:22
von NicTheQuick
Ist es nicht eher so?

Code: Alles auswählen

MessageRequester("FW_Version", Example\Main\Text)
Hab's nicht getestet, aber zwei mal "FW_Version" fand ich merkwürdig.

Re: XML einlesen

Verfasst: 30.04.2012 12:57
von ts-soft
NicTheQuick hat Recht. Der Fehler ist aber nicht meiner, ich bin davon ausgegangen, dieser Text würde sich in der XML
des ersten Sourcs befinden, weil dann wäre mein Beispiel richtig.

Re: XML einlesen

Verfasst: 30.04.2012 13:34
von STARGÅTE
Da eine XML immer ein Hauptknoten haben muss, hatte ich mich damals dafür entschieden diesen Hauptknoten durch \Main anzusprechen, da es einfacher ist, und etwas kürzer, als dort auch \Node("") zu verwenden.

Auf Änderungswünsche kann ich natürlich eingehen.

Re: XML einlesen

Verfasst: 30.04.2012 14:20
von ts-soft
Ne, ist schon in Ordnung so. Problem war ja nur, das ich bei der Frage von kunstlust davon ausgegangen bin,
die Zeile befindet sich innerhalb desselben Main, wie im anderen Beispiel. Hätte er dazu gesagt, was man erst
aus seiner nicht funktionierenden Umsetzung entnehmen kann, das es alleinstehend ist, hätte ich auch gleich die
richtige Lösung gefunden :wink: