XML-tolkning. Analysera XML-data C arbetar med XML-exempel

Steg 1. Godkänd test (interaktion med GIS GMP-testkretsen) #GIS GMP-testtjänstadress:
gisgmp.wsdlLocation=http://213.59.255.182:7777/gateway/services/SID0003663?wsdl
gisgmp.wsdlLocation.endPoint=http://213.59.255.182:7777/gateway/services/SID0003663
Denna adress är registrerad i SP-inställningarna. Dessutom måste du registrera den i loggningsinställningsfilen och ange värdet SPÅR. Efter att ha angett de angivna värdena måste du starta SP och ACC-klienten (starta om den om den redan har startats). Därefter måste du utföra åtgärden från ROR eller Accounting Office/AU Ansökan om betalning av medel "Skapa betalningsinformation", om systemkontrollerna godkänns, kommer informationen att skapas om betalning. Som senare kommer att behöva lastas av.
Efter uppladdningen måste du kontrollera statusen med hjälp av åtgärden "Begär bearbetningsstatus". Därefter växlar ED Payment Information till statusen "Accepted by GIS GMP" -...

Given: MSG (meddelanden) tabell med många poster.
CREATETABLEmsg(idINTEGERNOTNULLPRIMARYKEY,descriptionCHAR(50)NOTNULL, date_createDATE);
Uppgift:
Det är nödvändigt att rensa tabellen på data/
Lösning: Det finns flera sätt att lösa detta problem. Nedan finns en beskrivning och ett exempel på var och en av dem.
Det enklaste sättet ( första alternativet) - exekvering av operatören för radering av poster. När du kör det kommer du att se resultatet (hur många poster som raderades). En praktisk sak när du behöver veta säkert och förstå om rätt data har raderats. MEN har nackdelar jämfört med andra alternativ för att lösa problemet.

DELETE FROMmsg;--Raderar alla rader i tabellen --Raderar alla rader med skapandedatum "2019.02.01" DELETE FROMmsg WHEREdate_create="2019.02.01";

Andra alternativet. Använda DML-satsen för att rensa alla rader i en tabell.
TRUNCATETABLE meddelanden;
Det finns flera funktioner för att använda denna operatör:
Det är inte tillgängligt i Firebird, så vi använder det första och tredje alternativet. Efter avslutad...

Aktuella adresser för förfrågningar till SMEV 3.0 Vi påminner dig om att, i enlighet med tidigare publicerad information på SMEV 3.0 Technology Portal, är det nödvändigt att använda de aktuella adresserna för Unified Electronic Service:
adressen till den enhetliga elektroniska tjänsten för SMEV 3.0-utvecklingsmiljön, motsvarande schema 1.1 - http://smev3-d.test.gosuslugi.ru:7500/smev/v1.1/ws?wsdl, och tjänsten kommer också att vara tillgänglig kl

XML Extensible Markup Language är en uppsättning regler för kodning av dokument i maskinläsbar form. XML är ett populärt format för utbyte av data på Internet. Webbplatser som ofta uppdaterar sitt innehåll, till exempel nyhetssajter eller bloggar, tillhandahåller ofta ett XML-flöde så att externa program är medvetna om innehållsförändringar. Att skicka och analysera XML-data är en vanlig uppgift för applikationer med nätverksanslutning. Den här lektionen förklarar hur man analyserar XML-dokument och använder deras data.

Att välja en Parser

Kanalanalys

Det första steget i att analysera ett flöde är att bestämma vilka datafält du är intresserad av. Parsern extraherar de givna fälten och ignorerar allt annat.

Här är ett utdrag av kanalen som kommer att utforskas i exempelapplikationen. Varje inlägg på StackOverflow.com visas i ett flöde som en ingångstagg, som innehåller flera undertaggar:

senaste frågorna taggade android - Stack Overflow ... ... http://stackoverflow.com/q/9439999 0 Var är min datafil? cliff2310 http://stackoverflow.com/users/1128925 2012-02-25T00:30:54Z 2012-02-25T00:30:54Z

Jag har ett program som kräver en datafil...

... ...

Exempelapplikationen hämtar data från ingångstaggen och dess undertaggar titel, länk och sammanfattning.

Skapar en parserinstans

Nästa steg är att instansiera tolken och starta tolkningsprocessen. Det här utdraget initierar tolken så att den inte hanterar namnutrymmen och använder den tillhandahållna InputStream som indata. Parsingprocessen börjar med ett anrop till nextTag() och anropar metoden readFeed() som hämtar och bearbetar data som applikationen är intresserad av:

Public class StackOverflowXmlParser ( // Vi använder inte namnutrymmen privat statisk final String ns = null; public List parse(InputStream in) kastar XmlPullPullParserException, IOException ( try ( XmlPullParser parser = Xml.newPullParser(); parserPullPullParser.SetPullParser.Set , false); parser.setInput(in, null); parser.nextTag(); returnera readFeed(parser); ) slutligen ( in.close(); ) ) ... )

Subtrahera kanal

Metoden readFeed() utför själva arbetet med att bearbeta flödet. Element markerade med "entry"-taggen är startpunkten för rekursiv bearbetning av kanalen. Om nästa tagg inte är en ingångstagg hoppas den över. Efter att hela "flödet" har bearbetats rekursivt, returnerar readFeed() en lista som innehåller de poster (inklusive kapslade dataobjekt) som hämtas från flödet. Denna lista returneras sedan av tolken.

Private List readFeed(XmlPullParser parser) kastar XmlPullParserException, IOException ( List entries = new ArrayList (); parser.require(XmlPullParser.START_TAG, ns, "feed"); while (parser.next() !)= XmlPullPullar (parser.getEventType() != XmlPullParser.START_TAG) ( fortsätt; ) String name = parser.getName(); // Börjar med att leta efter entry-taggen if (name.equals("entry")) ( entries.add( readEntry(parser)); ) else ( skip(parser); ) ) returnerar poster; )

XML-tolkning

Stegen för att analysera XML-flödet är följande:

Det här utdraget visar hur tolkaren analyserar post, titel, länk och sammanfattning.

Public static class Entry ( public final String title; public final String link; public final String summary; private Entry(String title, String summary, String link) ( this.title = title; this.summary = summary; this.link = länk ; ) ) // Analyserar innehållet i en post. Om den stöter på en titel, sammanfattning eller länktagg lämnar du dem // till deras respektive "läs" metoder för bearbetning. I annat fall, hoppa över taggen. privat post readEntry(XmlPullParser parser) kastar XmlPullParserException, IOException ( parser.require(XmlPullParser.START_TAG, ns, "entry"); String title = null; String summary = null; String länk = null; while (parser() = XmlPullParser.END_TAG) ( if (parser.getEventType() != XmlPullParser.START_TAG) ( fortsätt; ) String name = parser.getName(); if (name.equals("title")) ( title = readTitle(parser) ; ) else if (name.equals("sammanfattning")) ( summary = readSummary(parser); ) else if (name.equals("link")) ( länk = readLink(parser); ) else ( skip(parser) ; ) ) returnera ny post (titel, sammanfattning, länk); ) // Bearbetar titeltaggar i flödet. private String readTitle(XmlPullParser parser) kastar IOException, XmlPullParserException ( parser.require(XmlPullParser.START_TAG, ns, "title"); String title = readText(parser); parser.require(XmlPullParserns.), "END_TAG", return title; ) // Behandlar länktaggar i flödet. private String readLink(XmlPullParser parser) kastar IOException, XmlPullParserException ( String link = ""; parser.require(XmlPullParser.START_TAG, ns, "link"); String tag = parser.getName(); String triburelType = parser.alueA( , "rel"); if (tag.equals("länk")) (if (relType.equals("alternate"))( länk = parser.getAttributeValue(null, "href"); parser.nextTag(); ) ) parser.require(XmlPullParser.END_TAG, ns, "länk"); returlänk; ) // Bearbetar sammanfattningstaggar i flödet. privat String readSummary(XmlPullParser parser) kastar IOException, XmlPullParserException ( parser.require(XmlPullParser.START_TAG, ns, "summary"); String summary = readText(parser); parser.require(XmlPullPar,yerns.END_TAGmar,yerns.); returnera sammanfattning; ) // För taggarna titel och sammanfattning, extraherar deras textvärden. private String readText(XmlPullParser parser) kastar IOException, XmlPullParserException ( String result = ""; if (parser.next() == XmlPullParser.TEXT) ( result = parser.getText(); parser.nextTag(); ) returnera resultat; ) ... )

Hoppa över saker du inte behöver

I ett av XML-analysstegen som beskrivs ovan hoppar parsern över taggar som vi inte är intresserade av. Nedan finns parserkoden för skip()-metoden:

Private void skip(XmlPullParser parser) kastar XmlPullParserException, IOException (if (parser.getEventType() != XmlPullParser.START_TAG) (kasta ny IllegalStateException(); ) int depth = 1; while (depth) ( switch != 0 next()) (case XmlPullParser.END_TAG: depth--; break; case XmlPullParser.START_TAG: depth++; break; ) ) )

Så här fungerar det:

  • Metoden skapar ett undantag om den aktuella händelsen inte är START_TAG .
  • Den förbrukar START_TAG och alla händelser upp till END_TAG.
  • För att se till att den stannar vid rätt END_TAG och inte den första taggen efter den ursprungliga START_TAG, håller den reda på häckningsdjupet.

Således, om det aktuella elementet har kapslade element, kommer värdet på djupet inte att vara 0 förrän parsern har bearbetat alla händelser mellan den ursprungliga START_TAG och dess motsvarande END_TAG. Tänk till exempel på hur analysatorn passerar ett element som har 2 kapslade element, Och :

  • Vid den första passagen genom while-slingan, nästa tagg som analysatorn stöter på efter detta är START_TAG för
  • Vid den andra passagen genom while-slingan är nästa tagg som analysatorn stöter på END_TAG
  • Vid den tredje passagen genom while-slingan är nästa tagg som analysatorn stöter på START_TAG . Djupvärdet ökas till 2.
  • Vid den fjärde passagen genom while-slingan är nästa tagg som analysatorn stöter på END_TAG. Djupvärdet reduceras till 1.
  • På den femte och sista passagen genom while-slingan är nästa tagg som analysatorn stöter på END_TAG. Djupvärdet reduceras till 0, vilket indikerar att elementet hoppades över.

XML-databehandling

Exempelapplikationen tar emot och analyserar ett XML-flöde i en AsyncTask. Bearbetning sker utanför huvudgränssnittstråden. När bearbetningen är klar uppdaterar applikationen användargränssnittet i huvudaktiviteten (NetworkActivity).

I utdraget nedan gör metoden loadPage() följande:

  • Initierar en strängvariabel med en URL som pekar på ett XML-flöde.
  • Om användarinställningarna och nätverksanslutningen tillåter, anropar nya DownloadXmlTask().execute(url) . Detta skapar ett nytt DownloadXmlTask-objekt (AsyncTask-underklass) och exekverar dess execute()-metod, som laddar ner och analyserar pipen och returnerar ett strängresultat som kommer att visas i användargränssnittet.
public class NetworkActivity utökar aktivitet (public static final String WIFI = "Wi-Fi"; public static final String ANY = "Val som helst"; privat statisk slutlig sträng URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort =nyaste"; // Om det finns en Wi-Fi-anslutning. privat static boolean wifiConnected = false; // Om det finns en mobilanslutning. private static boolean mobileConnected = false; // Om skärmen ska uppdateras. public static boolean refreshDisplay = true; public static String sPref = null; ... // Använder AsyncTask för att ladda ner XML-flödet från stackoverflow.com. public void loadPage() ( if((sPref.equals(ANY)) && (wifiConnected || mobileConnected )) ( new DownloadXmlTask().execute(URL); ) else if ((sPref.equals(WIFI)) && (wifiConnected)) ( new DownloadXmlTask().execute(URL); ) else ( // show error ) )
  • doInBackground() kör metoden loadXmlFromNetwork(). Den skickar kanalens URL som en parameter. Metoden loadXmlFromNetwork() tar emot och bearbetar kanalen. När den är klar skickar den tillbaka den resulterande strängen.
  • onPostExecute() tar den returnerade strängen och visar den i användargränssnittet.
// Implementering av AsyncTask som används för att ladda ner XML-flöde från stackoverflow.com. privatklass DownloadXmlTask ​​utökar AsyncTask ( @Override skyddad String doInBackground(String... urls) ( try ( return loadXmlFromNetwork(urls); ) catch (IOException e) ( return getResources().getString(R.string.connection_error); ) catch (XmlPullParserException e) ( return getResources().getString(R.string.xml_error); ) ) @Override protected void onPostExecute(String result) ( setContentView(R.layout.main); // Visar HTML-strängen i användargränssnittet via en WebView WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.loadData(result, "text/html", null); ) )

Nedan finns metoden loadXmlFromNetwork() som anropas från DownloadXmlTask. Den gör följande:

  1. Skapar en instans av StackOverflowXmlParser. Det skapar också variabler för List Entry-objekt, och titel, url och sammanfattning, för att lagra värdena som extraherats från XML-flödet för dessa fält.
  2. Anropar downloadUrl() som laddar ner kanalen och returnerar den som en InputStream.
  3. Använder StackOverflowXmlParser för att analysera en InputStream. StackOverflowXmlParser fyller listposter med data från flödet.
  4. Bearbetar poster Lista och kombinerar kanaldata med HTML-uppmärkning.
  5. Returnerar HTML-strängen som visas i gränssnittet för huvudaktiviteten, AsyncTask, i metoden onPostExecute().
// Laddar upp XML från stackoverflow.com, analyserar det och kombinerar det med // HTML-uppmärkning. Returnerar HTML-sträng. private String loadXmlFromNetwork(String urlString) kastar XmlPullParserException, IOException ( InputStream stream = null; // Instantiera parsern StackOverflowXmlParser stackOverflowXmlParser = new StackOverflowXmlParser(); poster = null; Strängtitel = null; String url = null; Strängsammanfattning = null; Calendar rightNow = Calendar.getInstance(); DateFormat formatter = new SimpleDateFormat("MMM dd h:mmaa"); // Kontrollerar om användaren ställer in inställningen att inkludera sammanfattningstext SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); boolean pref = sharedPrefs.getBoolean("summaryPref", false); StringBuilder htmlString = new StringBuilder(); htmlString.append("

" + getResources().getString(R.string.page_title) + "

"); htmlString.append(" " + getResources().getString(R.string.updated) + " " + formatter.format(rightNow.getTime()) + ""); try ( stream = downloadUrl(urlString); entries = stackOverflowXmlParser.parse(stream); // Ser till att InputStream stängs efter att appen har // slutat använda den. ) slutligen ( if (stream != null) ( stream.close(); ) ) // StackOverflowXmlParser returnerar en lista (kallad "entries") med Entry-objekt. // Varje Entry-objekt representerar ett enda inlägg i XML-flödet. // Det här avsnittet bearbetar postlistan för att kombinera varje post med HTML-uppmärkning. // Varje post visas i användargränssnittet som en länk som eventuellt innehåller // en textsammanfattning. för (Entry entry: entries) ( htmlString.append("

" + entry.title + "

"); // Om användaren ställer in inställningen att inkludera sammanfattningstext, // lägger till den i displayen. if (pref) ( htmlString.append(entry.summary); ) ) return htmlString.toString(); ) // Givet en strängrepresentation av en URL, upprättar en anslutning och får // en ingångsström. private InputStream downloadUrl(String urlString) kastar IOException ( URL url = new URL(urlString); HttpURLConnection conn = (HttpURLConnection) url.openConnection() ; conn.setReadTimeout(10000 /* millisekunder */); conn.setConnectTimeout(15000 /* millisekunder */); conn.setRequestMethod("GET"); conn.setDoInput(true); // Startar frågan conn.connect( ); returnera conn.getInputStream(); )
publicering av denna artikel är endast tillåten med en länk till artikelförfattarens webbplats

I den här artikeln kommer jag att visa ett exempel på hur man analyserar en stor XML-fil. Om din server (hosting) inte förbjuder att öka körtiden för skriptet, kan du analysera en XML-fil som väger minst gigabyte; jag personligen analyserade bara filer från ozon som vägde 450 megabyte.

När man analyserar stora XML-filer uppstår två problem:
1. Inte tillräckligt med minne.
2. Det finns inte tillräckligt med tid för att skriptet ska köras.

Det andra problemet med tid kan lösas om servern inte förbjuder det.
Men problemet med minne är svårt att lösa, även om vi pratar om din egen server, då är det inte särskilt lätt att flytta filer på 500 megabyte, och det är helt enkelt inte möjligt att öka minnet på hosting och VDS.

PHP har flera inbyggda XML-behandlingsalternativ - SimpleXML, DOM, SAX.
Alla dessa alternativ beskrivs i detalj i många artiklar med exempel, men alla exempel visar att man arbetar med ett fullständigt XML-dokument.

Här är ett exempel, att hämta ett objekt från en XML-fil

Nu kan du bearbeta detta objekt, MEN...
Som du kan se läses hela XML-filen in i minnet, sedan tolkas allt till ett objekt.
Det vill säga, all data går in i minnet och om det inte finns tillräckligt med tilldelat minne stoppas skriptet.

Det här alternativet är inte lämpligt för att bearbeta stora filer, du måste läsa filen rad för rad och bearbeta dessa data en efter en.
I det här fallet utförs även giltighetskontrollen i takt med att uppgifterna bearbetas, så du behöver kunna återställa, till exempel, radera all data som matats in i databasen vid en ogiltig XML-fil, eller utföra två pass genom filen, läs först för giltighet, läs sedan för bearbetning av data.

Här är ett teoretiskt exempel på att analysera en stor XML-fil.
Detta skript läser ett tecken i taget från en fil, samlar in denna data i block och skickar den till XML-tolken.
Detta tillvägagångssätt löser helt minnesproblemet och orsakar ingen belastning, men förvärrar problemet med tiden. Hur du försöker lösa problemet över tid, läs nedan.

Funktion webi_xml ($file)
{

########
### datafunktion

{
skriv ut $data ;
}
############################################



{
skriv ut $namn ;
print_r($attrs);
}


## avslutande taggfunktion
function endElement ($parser, $name)
{
skriv ut $namn ;
}
############################################

($xml_parser, "data");

// öppna filen
$fp = fopen($fil, "r");

$perviy_vxod = 1 ; $data = "" ;



{

$simvol = fgetc ($fp); $data .= $simvol ;


if($simvol != ">" ) (fortsätt;)


eka"

ha sönder;
}

$data = "" ;
}
fclose($fp);

Webi_xml("1.xml");

?>

I det här exemplet lägger jag allt i en funktion webi_xml() och längst ner kan du se dess anrop.
Själva skriptet består av tre huvudfunktioner:
1. En funktion som fångar öppningen av startElement()-taggen
2. En funktion som fångar den avslutande taggen endElement().
3. Och datamottagningsfunktionen data() .

Låt oss anta att innehållet i fil 1.xml är ett recept



< title >Enkelt bröd
< ingredient amount = "3" unit = "стакан" >Mjöl
< ingredient amount = "0.25" unit = "грамм" >Jäst
< ingredient amount = "1.5" unit = "стакан" >Varmvatten
< ingredient amount = "1" unit = "чайная ложка" >Salt
< instructions >
< step > Blanda alla ingredienser och knåda ordentligt.
< step > Täck med en trasa och låt stå i en timme i ett varmt rum..
< step > Knåda igen, lägg på en plåt och sätt in i ugnen.
< step > Besök webbplatsens webbplats


Vi börjar allt med att anropa den allmänna funktionen webi_xml ("1.xml" );
Därefter startar parsern i denna funktion och konverterar alla taggnamn till versaler så att alla taggar har samma skiftläge.

$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);

Nu anger vi vilka funktioner som kommer att fungera för att fånga öppningen av en tagg, stängning och bearbetning av data

xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "data");

Därefter kommer öppningen av den angivna filen, itererande genom filen ett tecken i taget och varje tecken läggs till i strängvariabeln tills tecknet hittas > .
Om detta är den allra första åtkomsten till filen, så raderas på vägen allt som är onödigt i början av filen, allt som kommer före , det här är taggen som XML ska börja med.
För första gången kommer en strängvariabel att innehålla en sträng

Och skicka den till demonteraren
xml_parse ($xml_parser, $data, feof ($fp));
Efter bearbetning av data återställs strängvariabeln och insamlingen av data till en sträng börjar igen och strängen bildas för andra gången

På den tredje
</b><br>den fjärde <br><b>Enkelt bröd

Observera att en strängvariabel alltid bildas från en färdig tagg > och det är inte nödvändigt att skicka inbrottstjuven en öppen och stängd tagg med exempelvis data
Enkelt bröd
Det är viktigt för denna hanterare att få en hel obruten tagg, minst en öppen tagg, och i nästa steg en stängd tagg, eller omedelbart få 1000 rader av en fil, det spelar ingen roll, huvudsaken är att taggen går inte sönder till exempel

le>Vanligt bröd
På så sätt är det omöjligt att skicka data till hanteraren, eftersom taggen är trasig.
Du kan komma på din egen metod för att skicka data till hanteraren, till exempel samla in 1 megabyte data och skicka den till hanteraren för att öka hastigheten, se bara till att taggarna alltid är färdiga och att data kan rivas
Enkel</b><br><b>bröd

Således, i delar som du vill, kan du skicka en stor fil till processorn.

Låt oss nu titta på hur denna data behandlas och hur man skaffar den.

Låt oss börja med öppningstaggarfunktionen startElement ($parser, $name, $attrs)
Låt oss anta att bearbetningen har nått gränsen
< ingredient amount = "3" unit = "стакан" >Mjöl
Sedan inuti funktionen kommer variabeln $name att vara lika med ingrediens det vill säga namnet på den öppna taggen (det har inte kommit till att stänga taggen än).
Även i det här fallet kommer en rad attribut för denna tagg $attrs att vara tillgängliga, som kommer att innehålla data mängd = "3" och enhet = "glas".

Efter detta bearbetades data för den öppna taggen av funktionen data ($parser, $data)
Variabeln $data kommer att innehålla allt som finns mellan öppnings- och stängningstaggar, i vårt fall är detta texten Muka

Och bearbetningen av vår sträng av funktionen avslutas endElement ($parser, $name)
Detta är namnet på den stängda taggen, i vårt fall kommer $name att vara lika med ingrediens

Och efter det gick allt i cirklar igen.

Ovanstående exempel visar bara principen för XML-bearbetning, men för verklig tillämpning måste den modifieras.
Vanligtvis måste du analysera stor XML för att mata in data i databasen, och för att korrekt bearbeta data behöver du veta vilken öppen tagg data tillhör, vilken nivå av taggkapsling och vilka taggar som är öppna i hierarkin ovan. Med denna information kan du bearbeta filen korrekt utan problem.
För att göra detta måste du introducera flera globala variabler som samlar in information om öppna taggar, kapsling och data.
Här är ett exempel som du kan använda

Funktion webi_xml ($file)
{
global $webi_depth ; // motverka till spår häckningsdjup
$webi_depth = 0 ;
global $webi_tag_open ; // kommer att innehålla en array av för närvarande öppna taggar
$webi_tag_open = array();
global $webi_data_temp ; // denna array kommer att innehålla data för en tagg

####################################################
### datafunktion
funktionsdata ($parser, $data)
{
global $webi_depth ;
global $webi_tag_open ;
global $webi_data_temp ;
// lägg till data till arrayen som indikerar kapsling och för närvarande öppen tagg
$webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ "data" ].= $data ;
}
############################################

####################################################
### öppningstaggfunktion
funktion startElement ($parser, $name, $attrs)
{
global $webi_depth ;
global $webi_tag_open ;
global $webi_data_temp ;

// om kapslingsnivån inte längre är noll, är en tagg redan öppen
// och data från den redan finns i arrayen kan du bearbeta den
if ($webi_depth)
{




" ;

skriv ut "
" ;
print_r($webi_tag_open); // rad öppna taggar
skriv ut "


" ;

// efter bearbetning av data, radera den för att frigöra minne
unset($GLOBALS [ "webi_data_temp" ][ $webi_depth ]);
}

// nu öppnas nästa tagg och ytterligare bearbetning kommer att ske i nästa steg
$webi_depth++; // öka häckningen

$webi_tag_open [ $webi_depth ]= $namn ; // lägg till en öppen tagg till informationsmatrisen
$webi_data_temp [ $webi_depth ][ $name ][ "attrs" ]= $attrs ; // lägg nu till taggattribut

}
###############################################

#################################################
## avslutande taggfunktion
function endElement ($parser, $name) (
global $webi_depth ;
global $webi_tag_open ;
global $webi_data_temp ;

// databehandling börjar här, till exempel lägga till i databasen, spara till en fil, etc.
// $webi_tag_open innehåller en kedja av öppna taggar efter kapslingsnivå
// till exempel $webi_tag_open[$webi_depth] innehåller namnet på den öppna taggen vars information för närvarande bearbetas
// $webi_depth tagg kapslingsnivå
// $webi_data_temp[$webi_depth][$webi_tag_open[$webi_depth]]["attrs"] rad med taggattribut
// $webi_data_temp[$webi_depth][$webi_tag_open[$webi_depth]]["data"] taggdata

Skriv ut "data" . $webi_tag_open [ $webi_depth ]. "--" .($webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ "data" ]). "
" ;
print_r ($webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ "attrs" ]);
skriv ut "
" ;
print_r($webi_tag_open);
skriv ut "


" ;

Unset($GLOBALS ["webi_data_temp"]); // efter att ha bearbetat data, tar vi bort hela arrayen med data, eftersom taggen stängdes
unset($GLOBALS [ "webi_tag_open" ][ $webi_depth ]); // radera information om denna öppna tag... sedan den stängdes

$webi_depth --; // minska häckningen
}
############################################

$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);

// indikerar vilka funktioner som kommer att fungera när taggar öppnas och stängs
xml_set_element_handler($xml_parser, "startElement", "endElement");

// ange en funktion för att arbeta med data
xml_set_character_data_handler($xml_parser, "data");

// öppna filen
$fp = fopen($fil, "r");

$perviy_vxod = 1 ; // flagga för att kontrollera den första posten i filen
$data = "" ; // här samlar vi in ​​data från filen i delar och skickar den till xml-parsern

// loop tills slutet av filen hittas
while (! feof ($fp ) och $fp )
{
$simvol = fgetc ($fp); // läs ett tecken från filen
$data .= $simvol ; // lägg till detta tecken till data som ska skickas

// om tecknet inte är sluttaggen, gå tillbaka till början av loopen och lägg till ytterligare ett tecken till data, och så vidare tills sluttaggen hittas
if($simvol != ">" ) (fortsätt;)
// om den avslutande taggen hittades kommer vi nu att skicka denna insamlade data för bearbetning

// kontrollera om detta är den första posten i filen, så raderar vi allt som finns före taggen// eftersom du ibland kan stöta på skräp före början av XML (klumpiga redigerare, eller filen togs emot av ett skript från en annan server)
if($perviy_vxod ) ( $data = strstr ($data , "

// Kasta nu data i xml-parsern
if (! xml_parse ($xml_parser, $data, feof ($fp))) (

// här kan du bearbeta och ta emot giltighetsfel...
// så snart ett fel påträffas, slutar tolkningen
eka"
XML-fel: " . xml_error_string(xml_get_error_code($xml_parser));
eko "vid linjen". xml_get_current_line_number ($xml_parser);
ha sönder;
}

// efter analys, kassera insamlade data för nästa steg i cykeln.
$data = "" ;
}
fclose($fp);
xml_parser_free($xml_parser);
// tar bort globala variabler
unset($GLOBALS ["webi_depth"]);
unset($GLOBALS ["webi_tag_open"]);
unset($GLOBALS ["webi_data_temp"]);

Webi_xml("1.xml");

?>

Hela exemplet åtföljs av kommentarer, nu testa och experimentera.
Observera att i funktionen att arbeta med data infogas data inte bara i en array, utan läggs till med " .=" eftersom datan kanske inte kommer fram i sin helhet, och om du bara gör en uppgift, då kommer du då och då att få informationen i bitar.

Tja, det är allt, nu finns det tillräckligt med minne när du bearbetar en fil av vilken storlek som helst, men skriptets körtid kan ökas på flera sätt.
Infoga en funktion i början av skriptet
set_time_limit(6000);
eller
ini_set ("max_exekveringstid" , "6000" );

Eller lägg till text i .htaccess-filen
php_value max_execution_time 6000

Dessa exempel kommer att öka skriptets körtid till 6000 sekunder.
Du kan bara öka tiden på detta sätt när säkert läge är avstängt.

Om du har tillgång till edit php.ini kan du öka tiden med att använda
max_execution_time = 6000

Till exempel, på Masterhost-hosting, när denna artikel skrivs, är det förbjudet att öka manustiden, trots säkert läge, men om du är ett proffs kan du skapa ditt eget php-bygge på masterhost, men det står inte i den här artikeln.

Några exempel i denna handledning inkluderar en XML-sträng. Istället för att upprepa det i varje exempel, lägg den här raden i en fil som du inkluderar i varje exempel. Denna linje visas i följande exempel. Dessutom kan du skapa ett XML-dokument och läsa det med funktionen simplexml_load_file().

Exempel #1 Exempel.php-fil med XML-sträng

$xmlstr =<<


PHP: Uppkomsten av Parser


Fröken. Kodare
Onlivia Actora


Herr. Kodare
El skådespelare


Så det är ett språk. Det är fortfarande ett programmeringsspråk. Eller
är detta ett skriptspråk? Allt avslöjas i den här dokumentären,
som en skräckfilm.




7
5


XML;
?>

SimpleXML är mycket lätt att använda! Försök att hämta en sträng eller ett nummer från det underliggande XML-dokumentet.

Exempel #2 Hämta en del av ett dokument

inkludera "exempel.php" ;

echo $movies -> film [ 0 ]-> plot ;
?>

Så det är ett språk. Det är fortfarande ett programmeringsspråk. Eller är det ett skriptspråk? Allt avslöjas i denna skräckfilmsliknande dokumentär.

I PHP kan du komma åt ett element i ett XML-dokument som innehåller otillåtna tecken (som ett bindestreck) i sitt namn genom att omsluta elementnamnet i klammerparenteser och apostrofer.

Exempel #3 Att få ett snöre

inkludera "exempel.php" ;

echo $movies -> movie ->( "great-lines" )-> line ;
?>

Resultatet av att köra detta exempel:

PHP löser alla mina webbproblem

Exempel #4 Åtkomst till icke-unika element i SimpleXML

Om det finns flera instanser av underordnade element inom samma överordnade element, måste standard iterationsmetoder användas.

inkludera "exempel.php" ;

$movies = nytt SimpleXMLElement ($xmlstr );

/* För varje nod , kommer vi att visa namnet separat . */
foreach ($movies -> film -> karaktärer -> karaktär som $character ) (
echo $karaktär -> namn, "spelar", $karaktär -> skådespelare, PHP_EOL;
}

?>

Resultatet av att köra detta exempel:

Fröken. Coder spelar Onlivia Actora Mr. Coder spelar El Actor

Kommentar:

Egenskaper ( $movies->film i föregående exempel) är inte arrayer. Detta är ett itererbart objekt i form av en array.

Exempel #5 Använda attribut

Hittills har vi bara hämtat namn och värden på elementen. SimpleXML kan också komma åt elementattribut. Du kan komma åt ett elements attribut på samma sätt som arrayelement ( array).

inkludera "exempel.php" ;

$movies = nytt SimpleXMLElement ($xmlstr );

/* Åtkomstnod första filmen.
* Vi kommer också att visa en betygsskala. */
foreach ($movies -> film [ 0 ]-> betyg som $rating ) (
switch((sträng) $rating [ "typ" ]) ( // Hämta elementattribut efter index
case "tummen" :
echo $rating , "tummen upp" ;
ha sönder;
fallet "stjärnor":
echo $rating, "stjärnor";
ha sönder;
}
}
?>

Resultatet av att köra detta exempel:

7 tummen upp5 stjärnor

Exempel #6 Jämföra element och attribut med text

För att jämföra ett element eller attribut med en sträng, eller för att skicka det till en funktion som text, måste du casta det till en sträng med (sträng). Annars kommer PHP att behandla elementet som ett objekt.

inkludera "exempel.php" ;

$movies = nytt SimpleXMLElement ($xmlstr );

if ((sträng) $movies -> movie -> title == "PHP: The emergence of the Parser") {
skriva ut "Min favoritfilm.";
}

echo htmlentities ((sträng) $movies -> movie -> title );
?>

Resultatet av att köra detta exempel:

Min favoritfilm.PHP: Emergence of the Parser

Exempel #7 Att jämföra två element

Två SimpleXMLElement anses olika även om de pekar på samma objekt som i PHP 5.2.0.

inkludera "exempel.php" ;

$movies1 = nytt SimpleXMLElement ($xmlstr );
$movies2 = nytt SimpleXMLElement ($xmlstr );
var_dump($movies1 == $movies2); // false sedan PHP 5.2.0
?>

Resultatet av att köra detta exempel:

Exempel #8 Använda XPath

SimpleXML inkluderar inbyggt XPath-stöd. Sök igenom alla element :

inkludera "exempel.php" ;

$movies = nytt SimpleXMLElement ($xmlstr );

foreach ($movies -> xpath ("//character") som $character ) (
echo $karaktär -> namn, "spelar", $karaktär -> skådespelare, PHP_EOL;
}
?>

"// " fungerar som ett jokertecken. För att ange en absolut sökväg, utelämna ett av snedstrecket.

Resultatet av att köra detta exempel:

Fröken. Coder spelar Onlivia Actora Mr. Coder spelar av El Actor

Exempel #9 Inställningsvärden

Data i SimpleXML behöver inte vara oföränderlig. Objektet låter dig manipulera alla element.

inkludera "exempel.php" ;
$movies = nytt SimpleXMLElement ($xmlstr );

$movies -> film [ 0 ]-> tecken -> karaktär [ 0 ]-> name = "Fröken Coder" ;

echo $movies -> asXML();
?>

Resultatet av att köra detta exempel:

PHP: Uppkomsten av Parser Fröken Coder Onlivia Actora Herr. Kodare El skådespelare 7 5

Exempel #10 Lägga till element och attribut

Sedan PHP 5.1.3 har SimpleXML möjligheten att enkelt lägga till underordnade element och attribut.

inkludera "exempel.php" ;
$movies = nytt SimpleXMLElement ($xmlstr );

$character = $movies -> film [ 0 ]-> karaktärer -> addChild ("karaktär" );
$character -> addChild ("namn", "Mr. Parser" );
$character -> addChild ("skådespelare" , "John Doe" );

$rating = $movies -> film [ 0 ]-> addChild ( "rating", "PG" );
$rating -> addAttribute ("typ", "mpaa" );

echo $movies -> asXML();
?>

Resultatet av att köra detta exempel:

PHP: Uppkomsten av Parser Fröken. Kodare Onlivia Actora Herr. Kodare El skådespelare Herr. ParserJohn Doe Så det är ett språk. Det är fortfarande ett programmeringsspråk. Eller är det ett skriptspråk? Allt avslöjas i denna skräckfilmsliknande dokumentär. PHP löser alla mina webbproblem 7 5 PG

Exempel #11 Interagera med DOM

PHP kan konvertera XML-noder från SimpleXML till DOM-format och vice versa. Det här exemplet visar hur du kan ändra ett DOM-element i SimpleXML.

$dom = nytt DOMDocument ;
$dom -> loadXML ( "dumheter" );
om (! $dom ) (
eko "Fel vid analys av dokument";
utgång;
}

$books = simplexml_import_dom($dom);

echo $books -> bok [ 0 ]-> titel ;
?>

Resultatet av att köra detta exempel:

4 år sedan

Det finns ett vanligt "trick" som ofta föreslagits för att konvertera ett SimpleXML-objekt till en array, genom att köra det genom json_encode() och sedan json_decode(). Jag skulle vilja förklara varför detta är en dålig idé.

Helt enkelt för att hela poängen med SimpleXML är att vara enklare att använda och kraftfullare än en vanlig array. Du kan till exempel skrivabar -> baz [ "bing" ] ?> och det betyder samma sak sombar [ 0 ]-> baz [ 0 ][ "bing" ] ?> , oavsett hur många bar eller baz-element det finns i XML; och om du skriverbar [ 0 ]-> baz [ 0 ] ?> får du allt stränginnehåll i den noden - inklusive CDATA-sektioner - oavsett om den också har underordnade element eller attribut. Du har också tillgång till namnutrymmesinformation, möjligheten att göra enkla redigeringar av XML, och till och med möjligheten att "importera" till ett DOM-objekt, för mycket mer kraftfull manipulation. Allt detta går förlorat genom att förvandla objektet till en array istället för att läsa och förstå exemplen på den här sidan.

Dessutom, eftersom den inte är designad för detta ändamål, kommer konverteringen till JSON och tillbaka faktiskt att förlora information i vissa situationer. Till exempel kommer alla element eller attribut i ett namnområde helt enkelt att kasseras, och allt textinnehåll kommer att kasseras om ett element också har underordnade eller attribut. Ibland spelar det ingen roll, men om du får för vana att konvertera allt till arrayer kommer det att svida dig så småningom.

Naturligtvis kan du skriva en smartare konvertering, som inte hade dessa begränsningar, men vid den tidpunkten får du inget värde av SimpleXML alls, och du bör bara använda XML Parser-funktionerna på lägre nivå, eller XMLReader-klassen, för att skapa din struktur. Du kommer fortfarande inte att ha den extra bekvämlighetsfunktionaliteten hos SimpleXML, men det är din förlust.

2 år sedan

Om din xml-sträng innehåller booleaner kodade med "0" och "1", kommer du att stöta på problem när du castar elementet direkt till bool:

$xmlstr =<<

1
0

XML;
$values ​​= new SimpleXMLElement($xmlstr);
$truevalue = (bool)$values->truevalue; // Sann
$falsevalue = (bool)$values->falsevalue; // också sant!!!

Istället måste du kasta till sträng eller int först:

$truevalue = (bool)(int)$values->truevalue; // Sann
$falsevalue = (bool)(int)$values->falsevalue; // falskt

9 år sedan

Om du behöver mata ut giltig xml i ditt svar, glöm inte att ställa in din rubrikinnehållstyp till xml förutom att eko ut resultatet av asXML():

$xml = simplexml_load_file("...");
...
... xml-grejer
...

//output xml i ditt svar:
header("Content-Type: text/xml");
echo $xml -> asXML();
?>

9 år sedan

Från README-filen:

SimpleXML är tänkt att vara ett enkelt sätt att komma åt XML-data.

SimpleXML-objekt följer fyra grundläggande regler:

1) egenskaper betecknar element-iteratorer
2) numeriska index betecknar element
3) icke-numeriska index betecknar attribut
4) strängkonvertering gör det möjligt att komma åt TEXT-data

Vid iteration av egenskaper upprepas alltid tillägget
alla noder med det elementnamnet. Sålunda måste metoden child() vara
kallas att iterera över subnoder. Men gör också följande:
foreach ($obj->nodnamn som $elem) (
// gör något med $elem
}
resulterar alltid i iteration av "nodnamn"-element. Så inte längre
kontroll behövs för att särskilja antalet noder av den typen.

När ett element TEXT-data nås via en egenskap
då inkluderar resultatet inte TEXT-data för underelement.

Kända problem
============

På grund av motorproblem är det för närvarande inte möjligt att komma åt
ett underelement av index 0: $object->property.

8 år sedan

Att använda saker som: is_object($xml->modul->admin) för att kontrollera om det faktiskt finns en nod som heter "admin", verkar inte fungera som förväntat, eftersom simplexml alltid returnerar ett objekt - i så fall ett tomt - även om en viss nod inte finns.
För mig verkar den gamla goda funktionen tomma() fungera alldeles utmärkt i sådana fall.

8 år sedan

Ett snabbt tips om xpath-frågor och standardnamnrymder. Det ser ut som att XML-systemet bakom SimpleXML fungerar på samma sätt som jag tror att XML-systemet .NET använder: när man behöver adressera något i standardnamnutrymmet måste man deklarera namnområdet med registerXPathNamespace och sedan använda dess prefix till adressera annars i standardnamnområdet levande element.

$string =<<

Fyrtio vad?
Joe
Jane

Jag vet att det är svaret - men vad är frågan?


XML;

$xml = simplexml_load_string ($string);
$xml -> registerXPathNamespace("def" , "http://www.w3.org/2005/Atom");

$nodes = $xml -> xpath ("//def:document/def:title" );

?>

9 år sedan

Medan SimpleXMLElement påstår sig vara iterabel, är det gör inte verkar implementera standard Iterator-gränssnittsfunktioner som::next och::reset korrekt. Därför verkar, medan foreach() fungerar, funktioner som next(), current() eller each() inte fungera som du kan förvänta dig -- pekaren verkar aldrig röra sig eller återställs hela tiden.

6 år sedan

Om XML-dokumentets kodning inte är UTF-8, måste kodningsdeklarationen visas omedelbart efter version="..." och före fristående="...". Detta är ett krav i XML-standarden.

Om kodning av XML-dokument skiljer sig från UTF-8. Kodningsdeklarationen bör följa omedelbart efter versionen = "..." och före fristående = "...". Detta krav är standard XML.


Ok

Ryska språket. ryska språket
Allvarligt fel: Oupptäckt undantag "Undantag" med meddelandet "Sträng kunde inte tolkas som XML" i...


Topp